package jetbrains.mps.debugger.java.runtime.evaluation.model; /*Generated by MPS */ import jetbrains.mps.debugger.java.runtime.evaluation.container.EvaluationContainer; import org.apache.log4j.Logger; import org.apache.log4j.LogManager; import jetbrains.mps.project.Project; import jetbrains.mps.debugger.java.runtime.state.DebugSession; import org.jetbrains.annotations.NotNull; import org.jetbrains.mps.openapi.module.SModuleReference; import java.util.List; import org.jetbrains.mps.openapi.model.SNodeReference; import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes; import jetbrains.mps.debugger.java.runtime.evaluation.container.IEvaluationContainer; import jetbrains.mps.debugger.java.runtime.evaluation.container.EvaluationModule; import org.jetbrains.mps.openapi.model.SModel; import org.jetbrains.mps.openapi.model.SNode; import jetbrains.mps.smodel.ModelDependencyUpdate; import jetbrains.mps.internal.collections.runtime.ListSequence; import jetbrains.mps.internal.collections.runtime.IVisitor; import jetbrains.mps.smodel.ModelImports; import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; import org.jetbrains.mps.openapi.persistence.PersistenceFacade; import jetbrains.mps.debugger.java.runtime.evaluation.container.BaseLanguagesImportHelper; import jetbrains.mps.smodel.behaviour.BHReflection; import jetbrains.mps.core.aspects.behaviour.SMethodTrimmedId; import jetbrains.mps.smodel.action.SNodeFactoryOperations; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations; import java.util.Map; import jetbrains.mps.internal.collections.runtime.MapSequence; import java.util.LinkedHashMap; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations; import java.util.Set; import jetbrains.mps.internal.collections.runtime.SetSequence; import java.util.HashSet; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SConceptOperations; import jetbrains.mps.internal.collections.runtime.Sequence; import com.sun.jdi.InvalidStackFrameException; import org.apache.log4j.Level; import org.jetbrains.annotations.Nullable; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModelOperations; import jetbrains.mps.internal.collections.runtime.IWhereFilter; import org.jetbrains.mps.openapi.module.FindUsagesFacade; import org.jetbrains.mps.openapi.language.SAbstractConcept; import jetbrains.mps.ide.findusages.model.scopes.ModelsScope; import java.util.Collections; import jetbrains.mps.progress.EmptyProgressMonitor; import jetbrains.mps.smodel.ModuleRepositoryFacade; import org.jetbrains.mps.openapi.model.SModelName; import jetbrains.mps.smodel.SModelStereotype; import java.util.ArrayList; import jetbrains.mps.smodel.CopyUtil; import com.intellij.openapi.extensions.PluginId; import com.intellij.ide.plugins.PluginManager; import jetbrains.mps.debug.api.Debuggers; import jetbrains.mps.debugger.java.runtime.JavaDebugger; import java.io.File; import com.intellij.ide.plugins.IdeaPluginDescriptorImpl; import jetbrains.mps.internal.collections.runtime.ISelector; import org.jetbrains.mps.openapi.model.SReference; import jetbrains.mps.smodel.SNodePointer; public class EvaluationWithContextContainer extends EvaluationContainer { private static final Logger LOG = LogManager.getLogger(EvaluationWithContextContainer.class); private final boolean myIsInWatch; private boolean myVariablesInitialized = false; protected final EvaluationContext myEvaluationContext; public EvaluationWithContextContainer(Project project, DebugSession session, @NotNull SModuleReference containerModule, List<SNodeReference> nodesToImport, boolean isInWatch, _FunctionTypes._void_P1_E0<? super IEvaluationContainer> onNodeSetUp) { super(project, session, containerModule, nodesToImport, onNodeSetUp); myIsInWatch = isInWatch; myEvaluationContext = new StackFrameContext(session.getUiState()); } @Override protected void setUpNode(List<SNodeReference> nodesToImport) { EvaluationModule containerModule = (EvaluationModule) myContainerModule.resolve(myDebuggerRepository); SModel containerModel = myContainerModel.resolve(myDebuggerRepository); setUpDependencies(containerModule, containerModel); final SNode evaluatorNode = createEvaluatorNode(); containerModel.addRootNode(evaluatorNode); myNode = evaluatorNode.getReference(); createVars(); tryToImport(evaluatorNode, nodesToImport); // XXX updateImportedModels() likely could live with null here, accessory models may be imported directly new ModelDependencyUpdate(containerModel).updateUsedLanguages().updateImportedModels(myDebuggerRepository).updateModuleDependencies(myDebuggerRepository); } private void setUpDependencies(final EvaluationModule containerModule, SModel containerModel) { ListSequence.fromList(myEvaluationContext.getClassPath()).union(ListSequence.fromList(getDebuggerStubPath())).visitAll(new IVisitor<String>() { public void visit(String it) { containerModule.addClassPathItem(it); } }); containerModule.updateModelsSet(); ModelImports modelImports = new ModelImports(containerModel); modelImports.addUsedLanguage(MetaAdapterFactory.getLanguage(0x7da4580f9d754603L, 0x816251a896d78375L, "jetbrains.mps.debugger.java.evaluation")); modelImports.addUsedLanguage(MetaAdapterFactory.getLanguage(0x802088974572437dL, 0xb50e8f050cba9566L, "jetbrains.mps.debugger.java.privateMembers")); containerModule.addDependency(PersistenceFacade.getInstance().createModuleReference("6354ebe7-c22a-4a0f-ac54-50b52ab9b065(JDK)"), false); } private void tryToImport(final SNode evaluatorNode, List<SNodeReference> nodesToImport) { BaseLanguagesImportHelper helper = new EvaluationWithContextContainer.MyBaseLanguagesImportHelper(evaluatorNode); helper.tryToImport(((SNode) BHReflection.invoke(evaluatorNode, SMethodTrimmedId.create("getCode", null, "hASWOEj0jB"))), nodesToImport); } @Override protected SNode createEvaluatorNode() { SNode evaluatorConcept = SNodeFactoryOperations.createNewNode(SNodeFactoryOperations.asInstanceConcept(MetaAdapterFactory.getConcept(0x7da4580f9d754603L, 0x816251a896d78375L, 0x53c5060c6b18d925L, "jetbrains.mps.debugger.java.evaluation.structure.EvaluatorConcept")), null); SPropertyOperations.set(evaluatorConcept, MetaAdapterFactory.getProperty(0x7da4580f9d754603L, 0x816251a896d78375L, 0x53c5060c6b18d925L, 0x53c5060c6b19c79bL, "isShowContext"), "" + (myIsInWatch)); return evaluatorConcept; } private void createVars() { // 2 uses. setUpNode() is invoked within command; updateState runs new command itself fillVariables(SNodeOperations.cast(getNode(), MetaAdapterFactory.getConcept(0x7da4580f9d754603L, 0x816251a896d78375L, 0x53c5060c6b18d925L, "jetbrains.mps.debugger.java.evaluation.structure.EvaluatorConcept"))); } private void fillVariables(SNode evaluatorConcept) { try { _FunctionTypes._return_P1_E0<? extends SNode, ? super String> createClassifierType = new _FunctionTypes._return_P1_E0<SNode, String>() { public SNode invoke(String name) { return createClassifierType(name); } }; Map<String, VariableDescription> contextVariables = myEvaluationContext.getVariables(createClassifierType); Map<String, SNode> declaredVariables = MapSequence.fromMap(new LinkedHashMap<String, SNode>(16, (float) 0.75, false)); for (SNode var : ListSequence.fromList(SLinkOperations.getChildren(evaluatorConcept, MetaAdapterFactory.getContainmentLink(0x7da4580f9d754603L, 0x816251a896d78375L, 0x53c5060c6b18d925L, 0x53c5060c6b19c797L, "variables")))) { MapSequence.fromMap(declaredVariables).put(SPropertyOperations.getString(var, MetaAdapterFactory.getProperty(0x7da4580f9d754603L, 0x816251a896d78375L, 0x53c5060c6b18d926L, 0x4db8c07036eb94eeL, "lowLevelName")), var); } final Set<SNode> foundVars = SetSequence.fromSet(new HashSet<SNode>()); for (String variable : MapSequence.fromMap(contextVariables).keySet()) { String name = variable; SNode lowLevelVarNode = MapSequence.fromMap(declaredVariables).get(name); if (needUpdateVariables()) { // we should update variables if we are first time here or if we do not show context (i.e. in evaluation) if (lowLevelVarNode == null) { lowLevelVarNode = SConceptOperations.createNewNode(MetaAdapterFactory.getConcept(0x7da4580f9d754603L, 0x816251a896d78375L, 0x53c5060c6b18d926L, "jetbrains.mps.debugger.java.evaluation.structure.LowLevelVariable")); ListSequence.fromList(SLinkOperations.getChildren(evaluatorConcept, MetaAdapterFactory.getContainmentLink(0x7da4580f9d754603L, 0x816251a896d78375L, 0x53c5060c6b18d925L, 0x53c5060c6b19c797L, "variables"))).addElement(lowLevelVarNode); MapSequence.fromMap(declaredVariables).put(name, lowLevelVarNode); } MapSequence.fromMap(contextVariables).get(variable).updateLowLevelVariable(lowLevelVarNode); } SetSequence.fromSet(foundVars).addElement(lowLevelVarNode); } // now mark vars which are currently out of scope Sequence.fromIterable(MapSequence.fromMap(declaredVariables).values()).visitAll(new IVisitor<SNode>() { public void visit(SNode it) { SPropertyOperations.set(it, MetaAdapterFactory.getProperty(0x7da4580f9d754603L, 0x816251a896d78375L, 0x53c5060c6b18d926L, 0x554b4e03d5950431L, "isOutOfScope"), "" + (!(SetSequence.fromSet(foundVars).contains(it)))); } }); if (needUpdateVariables()) { // create static context type SLinkOperations.setTarget(evaluatorConcept, MetaAdapterFactory.getContainmentLink(0x7da4580f9d754603L, 0x816251a896d78375L, 0x53c5060c6b18d925L, 0x3f11b1341fa23615L, "contextNode"), myEvaluationContext.getStaticContextType(createClassifierType)); // create this SLinkOperations.setTarget(evaluatorConcept, MetaAdapterFactory.getContainmentLink(0x7da4580f9d754603L, 0x816251a896d78375L, 0x53c5060c6b18d925L, 0x3f11b1341fa23613L, "thisNode"), myEvaluationContext.getThisClassifierType(createClassifierType)); } // todo highlight when this type or static context type are invalid } catch (InvalidStackFrameException e) { if (LOG.isEnabledFor(Level.WARN)) { LOG.warn("InvalidStackFrameException", e); } } myVariablesInitialized = true; } @Override public void updateState() { super.updateState(); if (myDebugSession.getEvaluationProvider().canEvaluate()) { // createVars used to execute command (runWriteActionInCommand), hence I assume (a) we've got proper thread here // (b) there's need to run inside a command. Although it looks undoTransparent (the one that doesn't record any changes) // is suited much better here. myDebuggerRepository.getModelAccess().executeCommand(new Runnable() { public void run() { createVars(); } }); } } @Nullable private SNode createClassifierType(final String unitFqName) { SNode unit = findUnit(unitFqName); if (unit == null) { return null; } SNode classifierType = SConceptOperations.createNewNode(MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101de48bf9eL, "jetbrains.mps.baseLanguage.structure.ClassifierType")); SLinkOperations.setTarget(classifierType, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101de48bf9eL, 0x101de490babL, "classifier"), SNodeOperations.cast(unit, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier"))); return classifierType; } public SNode findUnit(final String unitName) { // I hate the next piece of code // (and this class in general, since it inherited a lot of the ugly stuff from the old evaluation code) SModel stub = findStubForFqName(modelFqNameFromUnitName(unitName)); if (stub != null) { SModel model = stub; SNode node = ListSequence.fromList(SModelOperations.nodes(model, MetaAdapterFactory.getInterfaceConcept(0x9ded098bad6a4657L, 0xbfd948636cfe8bc3L, 0x465516cf87c705a4L, "jetbrains.mps.lang.traceable.structure.UnitConcept"))).findFirst(new IWhereFilter<SNode>() { public boolean accept(SNode it) { return eq_v5yv3u_a0a0a0a0a0a0b0d0p(((String) BHReflection.invoke(it, SMethodTrimmedId.create("getUnitName", null, "4pl5GY7LKmR"))), unitName) && SNodeOperations.isInstanceOf(it, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier")); } }); if (node != null) { return node; } } FindUsagesFacade findUsages = FindUsagesFacade.getInstance(); SAbstractConcept concept = MetaAdapterFactory.getInterfaceConcept(0x9ded098bad6a4657L, 0xbfd948636cfe8bc3L, 0x465516cf87c705a4L, "jetbrains.mps.lang.traceable.structure.UnitConcept"); Set<SNode> instances = findUsages.findInstances(new ModelsScope(getCandidateNonStubModels(unitName)), Collections.singleton(concept), false, new EmptyProgressMonitor()); return SNodeOperations.cast(SetSequence.fromSet(instances).findFirst(new IWhereFilter<SNode>() { public boolean accept(SNode it) { return SNodeOperations.isInstanceOf(((SNode) it), MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier")) && ((String) BHReflection.invoke(SNodeOperations.cast(it, MetaAdapterFactory.getInterfaceConcept(0x9ded098bad6a4657L, 0xbfd948636cfe8bc3L, 0x465516cf87c705a4L, "jetbrains.mps.lang.traceable.structure.UnitConcept")), SMethodTrimmedId.create("getUnitName", null, "4pl5GY7LKmR"))).equals(unitName); } }), MetaAdapterFactory.getInterfaceConcept(0x9ded098bad6a4657L, 0xbfd948636cfe8bc3L, 0x465516cf87c705a4L, "jetbrains.mps.lang.traceable.structure.UnitConcept")); } @Nullable private SModel findStubForFqName(String fqName) { return new ModuleRepositoryFacade(myDebuggerRepository).getModelByName(new SModelName(fqName, SModelStereotype.JAVA_STUB).getValue()); } private boolean needUpdateVariables() { return !(myVariablesInitialized) || !(myIsInWatch); } @Override public EvaluationWithContextContainer copy(final boolean isInWatch, _FunctionTypes._void_P1_E0<? super IEvaluationContainer> onNodeSetUp) { final SNodeReference reference = myNode; return new EvaluationWithContextContainer(myProject, myDebugSession, myContainerModule, ListSequence.fromList(new ArrayList<SNodeReference>()), isInWatch, onNodeSetUp) { @Override protected SNode createEvaluatorNode() { SNode newEvaluator = (SNode) CopyUtil.copyAndPreserveId(reference.resolve(myDebuggerRepository), true); SPropertyOperations.set(newEvaluator, MetaAdapterFactory.getProperty(0x7da4580f9d754603L, 0x816251a896d78375L, 0x53c5060c6b18d925L, 0x53c5060c6b19c79bL, "isShowContext"), "" + (isInWatch)); return newEvaluator; } }; } public static List<String> getDebuggerStubPath() { PluginId apiPlugin = PluginManager.getPluginByClassName(Debuggers.class.getName()); PluginId javaPlugin = PluginManager.getPluginByClassName(JavaDebugger.class.getName()); List<File> paths = ListSequence.fromList(new ArrayList<File>()); ListSequence.fromList(paths).addSequence(ListSequence.fromList(((IdeaPluginDescriptorImpl) PluginManager.getPlugin(apiPlugin)).getClassPath())); ListSequence.fromList(paths).addSequence(ListSequence.fromList(((IdeaPluginDescriptorImpl) PluginManager.getPlugin(javaPlugin)).getClassPath())); return ListSequence.fromList(paths).select(new ISelector<File, String>() { public String select(File it) { return (String) it.getAbsolutePath(); } }).toListSequence(); } /*package*/ Iterable<SModel> getCandidateNonStubModels(String unitName) { final String modelFqName = modelFqNameFromUnitName(unitName); final ModuleRepositoryFacade mrf = new ModuleRepositoryFacade(myDebuggerRepository); return Sequence.fromIterable(Sequence.fromArray(SModelStereotype.values)).select(new ISelector<CharSequence, SModel>() { public SModel select(CharSequence stereotype) { return mrf.getModelByName(new SModelName(modelFqName, stereotype).getValue()); } }).where(new IWhereFilter<SModel>() { public boolean accept(SModel it) { return it != null; } }); } public static String modelFqNameFromUnitName(String unitName) { int lastDot = unitName.lastIndexOf('.'); return ((lastDot == -1 ? "" : unitName.substring(0, lastDot))); } private class MyBaseLanguagesImportHelper extends BaseLanguagesImportHelper { private final SNode myEvaluatorNode; public MyBaseLanguagesImportHelper(SNode evaluatorNode) { myEvaluatorNode = evaluatorNode; } @Override public SNode findVariable(final SReference variableReference) { SNode matchingVar = ListSequence.fromList(SLinkOperations.getChildren(myEvaluatorNode, MetaAdapterFactory.getContainmentLink(0x7da4580f9d754603L, 0x816251a896d78375L, 0x53c5060c6b18d925L, 0x53c5060c6b19c797L, "variables"))).findFirst(new IWhereFilter<SNode>() { public boolean accept(SNode variable) { return eq_v5yv3u_a0a0a0a0a0a0a2w(SNodePointer.deserialize(SPropertyOperations.getString(variable, MetaAdapterFactory.getProperty(0x7da4580f9d754603L, 0x816251a896d78375L, 0x53c5060c6b18d926L, 0x6db8b4aef007e84fL, "highLevelNodeId"))), SLinkOperations.getTargetNode(variableReference).getReference()); } }); if (matchingVar == null) { matchingVar = ListSequence.fromList(SLinkOperations.getChildren(myEvaluatorNode, MetaAdapterFactory.getContainmentLink(0x7da4580f9d754603L, 0x816251a896d78375L, 0x53c5060c6b18d925L, 0x53c5060c6b19c797L, "variables"))).findFirst(new IWhereFilter<SNode>() { public boolean accept(SNode variable) { return eq_v5yv3u_a0a0a0a0a0a0a1a2w(SPropertyOperations.getString(variable, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name")), SPropertyOperations.getString(SNodeOperations.cast(SLinkOperations.getTargetNode(variableReference), MetaAdapterFactory.getInterfaceConcept(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, "jetbrains.mps.lang.core.structure.INamedConcept")), MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"))); } }); } return matchingVar; } @Override public SNode createVariableReference(SNode variable) { SNode newVariableReference = SConceptOperations.createNewNode(MetaAdapterFactory.getConcept(0x7da4580f9d754603L, 0x816251a896d78375L, 0x7d9a547f857a394bL, "jetbrains.mps.debugger.java.evaluation.structure.LowLevelVariableReference")); SLinkOperations.setTarget(newVariableReference, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x4c4b92003e49a704L, 0x4c4b92003e49a705L, "baseVariableDeclaration"), variable); return newVariableReference; } } private static boolean eq_v5yv3u_a0a0a0a0a0a0b0d0p(Object a, Object b) { return (a != null ? a.equals(b) : a == b); } private static boolean eq_v5yv3u_a0a0a0a0a0a0a2w(Object a, Object b) { return (a != null ? a.equals(b) : a == b); } private static boolean eq_v5yv3u_a0a0a0a0a0a0a1a2w(Object a, Object b) { return (a != null ? a.equals(b) : a == b); } }