package jetbrains.mps.baseLanguage.util.plugin.refactorings; /*Generated by MPS */ import org.jetbrains.mps.openapi.model.SNode; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations; import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; import jetbrains.mps.internal.collections.runtime.ListSequence; import org.jetbrains.mps.openapi.language.SAbstractConcept; import jetbrains.mps.internal.collections.runtime.IWhereFilter; import jetbrains.mps.lang.dataFlow.framework.Program; import jetbrains.mps.lang.dataFlow.MPSProgramBuilder; import jetbrains.mps.lang.dataFlow.framework.AnalysisResult; import java.util.Set; import jetbrains.mps.lang.dataFlow.framework.instructions.WriteInstruction; import jetbrains.mps.lang.dataFlow.framework.analyzers.ReachingDefinitionsAnalyzer; import jetbrains.mps.lang.dataFlow.framework.instructions.Instruction; import jetbrains.mps.internal.collections.runtime.SetSequence; public class InlineVariableReferenceRefactoring extends InlineVariableRefactoring { private SNode myReference; private SNode myAssignment; public InlineVariableReferenceRefactoring(SNode node) { if (!(SNodeOperations.isInstanceOf(SLinkOperations.getTarget(node, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, 0xf8cc6bf960L, "variableDeclaration")), MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc67c7efL, "jetbrains.mps.baseLanguage.structure.LocalVariableDeclaration")))) { throw new IllegalArgumentException(); } this.myReference = node; this.findAssignment(node); } @Override public SNode doRefactoring() { final SNode variable = SLinkOperations.getTarget(this.myReference, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, 0xf8cc6bf960L, "variableDeclaration")); SNode nodeToSelect; if (myAssignment == null) { nodeToSelect = SNodeOperations.copyNode(SLinkOperations.getTarget(SLinkOperations.getTarget(this.myReference, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, 0xf8cc6bf960L, "variableDeclaration")), MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c37a7f6eL, 0xf8c37f506eL, "initializer"))); SNodeOperations.replaceWithAnother(this.myReference, nodeToSelect); } else if (SNodeOperations.isInstanceOf(myAssignment, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c37a7f6eL, "jetbrains.mps.baseLanguage.structure.VariableDeclaration"))) { nodeToSelect = SNodeOperations.copyNode(SLinkOperations.getTarget(SNodeOperations.cast(myAssignment, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c37a7f6eL, "jetbrains.mps.baseLanguage.structure.VariableDeclaration")), MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c37a7f6eL, 0xf8c37f506eL, "initializer"))); SNodeOperations.replaceWithAnother(this.myReference, nodeToSelect); } else if (SNodeOperations.isInstanceOf(myAssignment, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e96L, "jetbrains.mps.baseLanguage.structure.AssignmentExpression"))) { if (ListSequence.fromList(SNodeOperations.getNodeDescendants(SLinkOperations.getTarget(SNodeOperations.cast(myAssignment, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e96L, "jetbrains.mps.baseLanguage.structure.AssignmentExpression")), MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x11b0d00332cL, 0xf8c77f1e99L, "rValue")), MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, "jetbrains.mps.baseLanguage.structure.VariableReference"), false, new SAbstractConcept[]{})).where(new IWhereFilter<SNode>() { public boolean accept(SNode it) { return eq_uj3i4l_a0a0a0a0a0a0a0a2a3(SLinkOperations.getTarget(it, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, 0xf8cc6bf960L, "variableDeclaration")), variable); } }).isNotEmpty()) { // Assigments referring to the variable from their right side should not be inlined, since the resulting code will have different semantics than the original return myAssignment; } nodeToSelect = SNodeOperations.copyNode(SLinkOperations.getTarget(SNodeOperations.cast(myAssignment, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e96L, "jetbrains.mps.baseLanguage.structure.AssignmentExpression")), MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x11b0d00332cL, 0xf8c77f1e99L, "rValue"))); SNodeOperations.replaceWithAnother(this.myReference, nodeToSelect); this.optimizeAssignment(SNodeOperations.cast(myAssignment, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e96L, "jetbrains.mps.baseLanguage.structure.AssignmentExpression")), variable); } else { // ATM we do not inline if the last update was through a++ nor a+=1 type-of expressions return myAssignment; } this.optimizeDeclaration(variable); return nodeToSelect; } private void findAssignment(SNode node) { SNode variable = SLinkOperations.getTarget(node, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, 0xf8cc6bf960L, "variableDeclaration")); myAssignment = null; SNode currentList = SNodeOperations.getNodeAncestor(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b200L, "jetbrains.mps.baseLanguage.structure.StatementList"), false, false); SNode currentStatement; while ((myAssignment == null) && (currentList != null)) { currentStatement = getParentStatement(node, currentList); Program program = new MPSProgramBuilder().buildProgram(currentList); AnalysisResult<Set<WriteInstruction>> definitions = program.analyze(new ReachingDefinitionsAnalyzer()); for (Instruction nodeInstruction : ListSequence.fromList(program.getInstructionsFor(currentStatement))) { for (WriteInstruction instruction : SetSequence.fromSet(definitions.get(nodeInstruction))) { if (instruction.getVariable() == variable) { SNode assignmentNode = (SNode) instruction.getSource(); // We need to avoid inlining a self-assignment if (!(ListSequence.fromList(SNodeOperations.getNodeAncestors(node, null, false)).contains(assignmentNode))) { myAssignment = (assignmentNode); } } } } currentList = SNodeOperations.getNodeAncestor(currentList, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b200L, "jetbrains.mps.baseLanguage.structure.StatementList"), false, false); } } private SNode getParentStatement(SNode node, SNode list) { SNode curParent = node; while ((curParent != null) && SNodeOperations.getParent(curParent) != list) { curParent = SNodeOperations.getParent(curParent); } return SNodeOperations.cast(curParent, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b215L, "jetbrains.mps.baseLanguage.structure.Statement")); } private static boolean eq_uj3i4l_a0a0a0a0a0a0a0a2a3(Object a, Object b) { return (a != null ? a.equals(b) : a == b); } }