package jetbrains.mps.baseLanguage.util.plugin.refactorings;
/*Generated by MPS */
import java.util.List;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.mps.openapi.model.SNode;
import java.util.ArrayList;
import java.util.Map;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations;
import jetbrains.mps.internal.collections.runtime.SetSequence;
import jetbrains.mps.internal.collections.runtime.MapSequence;
import java.util.Set;
import jetbrains.mps.smodel.behaviour.BHReflection;
import jetbrains.mps.core.aspects.behaviour.SMethodTrimmedId;
import jetbrains.mps.internal.collections.runtime.ISelector;
import java.util.HashMap;
import org.jetbrains.mps.openapi.language.SAbstractConcept;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SConceptOperations;
import java.util.HashSet;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.mps.openapi.persistence.PersistenceFacade;
import jetbrains.mps.smodel.SModelUtil_new;
import org.jetbrains.mps.openapi.model.SNodeAccessUtil;
import jetbrains.mps.lang.typesystem.runtime.HUtil;
public abstract class ExtractMethodRefactoring {
protected ExtractMethodRefactoringParameters myParameters;
protected ExtractMethodRefactoringAnalyzer myAnalyzer;
private IStaticContainerProcessor myStaticContainer;
protected List<MethodMatch> myMatches;
public ExtractMethodRefactoring(ExtractMethodRefactoringParameters parameters) {
this.myParameters = parameters;
this.myAnalyzer = parameters.getAnalyzer();
}
@NotNull
public SNode doRefactor() {
SNode body = createMethodBody();
List<SNode> params = new ArrayList<SNode>();
Map<SNode, SNode> inputToParams = this.createInputParameters(body, params);
Map<SNode, SNode> inputMapping = this.createInputVaryablesMapping(inputToParams, this.myParameters.getNodesToRefactor());
this.myMatches = new MethodDuplicatesFinder(this.myParameters.getNodesToRefactor(), inputMapping, params, this.getOutputReferences()).findDuplicates(SNodeOperations.getNodeAncestor(ListSequence.fromList(this.myParameters.getNodesToRefactor()).first(), MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier"), false, false));
this.replaceInputVariablesByParameters(SLinkOperations.getChildren(body, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b200L, 0xf8cc6bf961L, "statement")), inputToParams);
SNode newMethod = this.createNewMethod(SNodeOperations.copyNode(this.getMethodType()), params, body);
this.addMethod(newMethod);
MethodMatch exactMatch = this.createMatch(this.myParameters.getNodesToRefactor(), inputMapping, params);
this.replaceMatch(exactMatch, newMethod);
MethodOptimizer.optimize(body);
return newMethod;
}
protected abstract SNode createMethodBody();
public abstract void replaceMatch(MethodMatch match, SNode methodDeclaration);
protected MethodMatch createMatch(List<SNode> nodes, Map<SNode, SNode> inputMapping, List<SNode> parametersOrder) {
MethodMatch match = new MethodMatch(parametersOrder);
for (SNode node : ListSequence.fromList(nodes)) {
match.putNode(node);
}
for (SNode node : SetSequence.fromSet(MapSequence.fromMap(inputMapping).keySet())) {
match.putMapping(node, MapSequence.fromMap(inputMapping).get(node));
}
return match;
}
protected SNode createNewMethod(SNode returnType, List<SNode> params, SNode body) {
SNode myMethod;
if (this.myStaticContainer != null) {
myMethod = this.myStaticContainer.createNewMethod();
} else {
IExtractMethodRefactoringProcessor processor = this.myAnalyzer.getExtractMethodReafactoringProcessor();
if (processor instanceof AbstractExtractMethodRefactoringProcessor) {
((AbstractExtractMethodRefactoringProcessor) processor).setStatic(this.myParameters.isStatic());
}
myMethod = processor.createNewMethod();
}
this.fillBaseMethodDeclaration(myMethod, returnType, params, body);
this.createNewDeclarations(myMethod);
this.correctThrowsList(myMethod);
return myMethod;
}
private void correctThrowsList(SNode method) {
List<SNode> throwables = new ArrayList<SNode>();
for (SNode statement : ListSequence.fromList(SLinkOperations.getChildren(SLinkOperations.getTarget(method, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b1fcL, 0xf8cc56b1ffL, "body")), MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b200L, 0xf8cc6bf961L, "statement")))) {
ListSequence.fromList(throwables).addSequence(SetSequence.fromSet(((Set<SNode>) BHReflection.invoke(statement, SMethodTrimmedId.create("uncaughtThrowables", MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b215L, "jetbrains.mps.baseLanguage.structure.Statement"), "4Gt7ANIVAVT"), ((boolean) false)))));
}
ListSequence.fromList(SLinkOperations.getChildren(method, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b1fcL, 0x10f383d6949L, "throwsItem"))).addSequence(ListSequence.fromList(throwables).select(new ISelector<SNode, SNode>() {
public SNode select(SNode it) {
return _quotation_createNode_jq3ovj_a0a0a0a0c0k(it);
}
}));
}
protected void createNewDeclarations(SNode method) {
Map<SNode, List<SNode>> mapping = MapSequence.fromMap(new HashMap<SNode, List<SNode>>());
for (SNode reference : ListSequence.fromList(SNodeOperations.getNodeDescendants(method, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, "jetbrains.mps.baseLanguage.structure.VariableReference"), false, new SAbstractConcept[]{}))) {
SNode declaration = SLinkOperations.getTarget(reference, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, 0xf8cc6bf960L, "variableDeclaration"));
if (!((SNodeOperations.isInstanceOf(declaration, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e94L, "jetbrains.mps.baseLanguage.structure.ParameterDeclaration")) || SNodeOperations.isInstanceOf(declaration, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc67c7efL, "jetbrains.mps.baseLanguage.structure.LocalVariableDeclaration"))))) {
continue;
}
if (!(ListSequence.fromList(SNodeOperations.getNodeAncestors(declaration, null, false)).contains(method))) {
if (!(SetSequence.fromSet(MapSequence.fromMap(mapping).keySet()).contains(declaration))) {
MapSequence.fromMap(mapping).put(declaration, new ArrayList<SNode>());
}
ListSequence.fromList(MapSequence.fromMap(mapping).get(declaration)).addElement(reference);
}
}
for (SNode declaration : SetSequence.fromSet(MapSequence.fromMap(mapping).keySet())) {
SNode newDeclaration = _quotation_createNode_jq3ovj_a0a0c0l(SNodeOperations.copyNode(SLinkOperations.getTarget(declaration, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x450368d90ce15bc3L, 0x4ed4d318133c80ceL, "type"))), SPropertyOperations.getString(declaration, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name")));
SNodeOperations.insertPrevSiblingChild(ListSequence.fromList(SLinkOperations.getChildren(SLinkOperations.getTarget(method, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b1fcL, 0xf8cc56b1ffL, "body")), MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b200L, 0xf8cc6bf961L, "statement"))).first(), _quotation_createNode_jq3ovj_a0a1a2a11(newDeclaration));
for (SNode reference : ListSequence.fromList(MapSequence.fromMap(mapping).get(declaration))) {
SNodeOperations.replaceWithAnother(reference, ((SNode) BHReflection.invoke(newDeclaration, SMethodTrimmedId.create("createReference", null, "hEwJfME"))));
}
}
}
protected SNode fillBaseMethodDeclaration(SNode declaration, SNode returnType, List<SNode> params, SNode body) {
if (SNodeOperations.isInstanceOf(declaration, MetaAdapterFactory.getInterfaceConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x112670d273fL, "jetbrains.mps.baseLanguage.structure.IVisible"))) {
SNode visibleDeclaration = SNodeOperations.cast(declaration, MetaAdapterFactory.getInterfaceConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x112670d273fL, "jetbrains.mps.baseLanguage.structure.IVisible"));
SLinkOperations.setTarget(visibleDeclaration, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x112670d273fL, 0x112670d886aL, "visibility"), this.myParameters.getVisibilityLevel().getNode());
}
SNode methodDeclaration = declaration;
SLinkOperations.setTarget(methodDeclaration, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b1fcL, 0xf8cc56b1fdL, "returnType"), SNodeOperations.copyNode(returnType));
SPropertyOperations.set(methodDeclaration, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"), this.myParameters.getName());
ListSequence.fromList(SLinkOperations.getChildren(methodDeclaration, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b1fcL, 0xf8cc56b1feL, "parameter"))).addSequence(ListSequence.fromList(params));
SLinkOperations.setTarget(methodDeclaration, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b1fcL, 0xf8cc56b1ffL, "body"), body);
return methodDeclaration;
}
protected void addMethod(SNode node) {
if (this.myStaticContainer == null) {
IExtractMethodRefactoringProcessor processor = this.myAnalyzer.getExtractMethodReafactoringProcessor();
processor.addMethod(node);
} else {
this.myStaticContainer.addMethod(node);
}
}
protected Map<SNode, SNode> createInputParameters(SNode body, List<SNode> parameters) {
Map<SNode, SNode> result = MapSequence.fromMap(new HashMap<SNode, SNode>());
for (MethodParameter methodParameter : ListSequence.fromList(this.myParameters.getParameters())) {
if (methodParameter.isSelected()) {
SNode parameter = SConceptOperations.createNewNode(MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e94L, "jetbrains.mps.baseLanguage.structure.ParameterDeclaration"));
SLinkOperations.setTarget(parameter, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x450368d90ce15bc3L, 0x4ed4d318133c80ceL, "type"), SNodeOperations.copyNode(methodParameter.getType()));
SPropertyOperations.set(parameter, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"), methodParameter.getName());
if (methodParameter.isFinal()) {
SPropertyOperations.set(parameter, MetaAdapterFactory.getProperty(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c37a7f6eL, 0x111f9e9f00cL, "isFinal"), "" + (true));
}
ListSequence.fromList(parameters).addElement(parameter);
MapSequence.fromMap(result).put(methodParameter.getDeclaration(), parameter);
}
}
return result;
}
public void replaceInputVariablesByParameters(List<SNode> nodes, Map<SNode, SNode> mapping) {
Map<SNode, SNode> anotherMap = this.createInputVaryablesMapping(mapping, nodes);
for (SNode node : SetSequence.fromSet(MapSequence.fromMap(anotherMap).keySet())) {
SNodeOperations.replaceWithAnother(node, _quotation_createNode_jq3ovj_a0a0a1a51(MapSequence.fromMap(anotherMap).get(node)));
}
}
public Map<SNode, SNode> createInputVaryablesMapping(Map<SNode, SNode> variableDeclarationToParameter, List<SNode> nodes) {
Map<SNode, SNode> mapping = MapSequence.fromMap(new HashMap<SNode, SNode>());
for (SNode node : ListSequence.fromList(nodes)) {
for (SNode reference : ListSequence.fromList(SNodeOperations.getNodeDescendants(node, MetaAdapterFactory.getConcept(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x10802efe25aL, "jetbrains.mps.lang.core.structure.BaseConcept"), false, new SAbstractConcept[]{}))) {
if (MoveRefactoringUtils.isReference(reference)) {
SNode target = ListSequence.fromList(SNodeOperations.getReferences(reference)).first().getTargetNode();
if (MapSequence.fromMap(variableDeclarationToParameter).containsKey(target)) {
MapSequence.fromMap(mapping).put(reference, MapSequence.fromMap(variableDeclarationToParameter).get(target));
}
}
}
for (SNode parameter : ListSequence.fromList(SNodeOperations.getNodeDescendants(node, MetaAdapterFactory.getInterfaceConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x11d486a1d9eL, "jetbrains.mps.baseLanguage.structure.IParameter"), false, new SAbstractConcept[]{}))) {
SNode declaration = ((SNode) BHReflection.invoke(parameter, SMethodTrimmedId.create("getDeclaration", null, "hP8xjWn")));
if (MapSequence.fromMap(variableDeclarationToParameter).containsKey(declaration)) {
MapSequence.fromMap(mapping).put(parameter, MapSequence.fromMap(variableDeclarationToParameter).get(declaration));
}
}
}
return mapping;
}
protected SNode createReference(SNode variable) {
return ((SNode) BHReflection.invoke(variable, SMethodTrimmedId.create("createReference", null, "hEwJfME")));
}
protected List<SNode> createCallParameters() {
List<SNode> result = new ArrayList<SNode>();
for (MethodParameter parameter : ListSequence.fromList(this.myParameters.getParameters())) {
if (parameter.isSelected()) {
ListSequence.fromList(result).addElement(parameter.getReference());
}
}
return result;
}
protected SNode createMethodCall(SNode methodDeclaration, List<SNode> parameters) {
if (this.myStaticContainer == null) {
IExtractMethodRefactoringProcessor processor = this.myAnalyzer.getExtractMethodReafactoringProcessor();
return processor.createMethodCall(methodDeclaration, parameters);
} else {
return this.myStaticContainer.createMethodCall(methodDeclaration, parameters);
}
}
public SNode createMethodCall(MethodMatch match, SNode methodDeclaration) {
return this.createMethodCall(methodDeclaration, match.getCallParameters());
}
public void setStaticContainer(SNode node) {
if (SNodeOperations.isInstanceOf(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c108ca66L, "jetbrains.mps.baseLanguage.structure.ClassConcept"))) {
this.myStaticContainer = new ClassStaticContainerProcessor(node);
} else if (SNodeOperations.isInstanceOf(node, MetaAdapterFactory.getInterfaceConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x11c8f444674L, "jetbrains.mps.baseLanguage.structure.IStaticContainerForMethods"))) {
SNode staticContainer = SNodeOperations.cast(node, MetaAdapterFactory.getInterfaceConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x11c8f444674L, "jetbrains.mps.baseLanguage.structure.IStaticContainerForMethods"));
this.myStaticContainer = ((IStaticContainerProcessor) BHReflection.invoke(staticContainer, SMethodTrimmedId.create("getStaticContainerProcessor", null, "hMfhg$W"), node));
} else {
throw new IllegalArgumentException();
}
}
public Set<SNode> getOutputReferences() {
Set<SNode> result = SetSequence.fromSet(new HashSet<SNode>());
List<SNode> outputVariables = myParameters.getAnalyzer().getOutputVariables();
for (SNode node : ListSequence.fromList(myParameters.getNodesToRefactor())) {
for (SNode varReference : ListSequence.fromList(SNodeOperations.getNodeDescendants(node, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, "jetbrains.mps.baseLanguage.structure.VariableReference"), false, new SAbstractConcept[]{}))) {
if (ListSequence.fromList(outputVariables).contains(SLinkOperations.getTarget(varReference, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, 0xf8cc6bf960L, "variableDeclaration")))) {
SetSequence.fromSet(result).addElement(varReference);
}
}
}
return result;
}
public List<MethodMatch> getMatches() {
return this.myMatches;
}
public ExtractMethodRefactoringAnalyzer getAnalyzer() {
return myParameters.getAnalyzer();
}
@Nullable
public abstract SNode getMethodType();
public boolean canBeStatic() {
return this.myAnalyzer.canBeStatic();
}
public boolean shouldBeStatic() {
return this.myAnalyzer.shouldBeStatic();
}
private static SNode _quotation_createNode_jq3ovj_a0a0a0a0c0k(Object parameter_1) {
PersistenceFacade facade = PersistenceFacade.getInstance();
SNode quotedNode_2 = null;
quotedNode_2 = SModelUtil_new.instantiateConceptDeclaration(MetaAdapterFactory.getConcept(MetaAdapterFactory.getLanguage(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, "jetbrains.mps.baseLanguage"), 0x101de48bf9eL, "ClassifierType"), null, null, false);
SNodeAccessUtil.setReferenceTarget(quotedNode_2, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101de48bf9eL, 0x101de490babL, "classifier"), (SNode) parameter_1);
return quotedNode_2;
}
private static SNode _quotation_createNode_jq3ovj_a0a0c0l(Object parameter_1, Object parameter_2) {
PersistenceFacade facade = PersistenceFacade.getInstance();
SNode quotedNode_3 = null;
SNode quotedNode_4 = null;
quotedNode_3 = SModelUtil_new.instantiateConceptDeclaration(MetaAdapterFactory.getConcept(MetaAdapterFactory.getLanguage(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, "jetbrains.mps.baseLanguage"), 0xf8cc67c7efL, "LocalVariableDeclaration"), null, null, false);
SNodeAccessUtil.setProperty(quotedNode_3, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"), (String) parameter_2);
quotedNode_4 = (SNode) parameter_1;
if (quotedNode_4 != null) {
quotedNode_3.addChild(MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x450368d90ce15bc3L, 0x4ed4d318133c80ceL, "type"), HUtil.copyIfNecessary(quotedNode_4));
}
return quotedNode_3;
}
private static SNode _quotation_createNode_jq3ovj_a0a1a2a11(Object parameter_1) {
PersistenceFacade facade = PersistenceFacade.getInstance();
SNode quotedNode_2 = null;
SNode quotedNode_3 = null;
SNode quotedNode_4 = null;
quotedNode_2 = SModelUtil_new.instantiateConceptDeclaration(MetaAdapterFactory.getConcept(MetaAdapterFactory.getLanguage(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, "jetbrains.mps.baseLanguage"), 0xf8cc67c7f0L, "LocalVariableDeclarationStatement"), null, null, false);
quotedNode_3 = (SNode) parameter_1;
if (quotedNode_3 != null) {
quotedNode_2.addChild(MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc67c7f0L, 0xf8cc67c7f1L, "localVariableDeclaration"), HUtil.copyIfNecessary(quotedNode_3));
}
return quotedNode_2;
}
private static SNode _quotation_createNode_jq3ovj_a0a0a1a51(Object parameter_1) {
PersistenceFacade facade = PersistenceFacade.getInstance();
SNode quotedNode_2 = null;
quotedNode_2 = SModelUtil_new.instantiateConceptDeclaration(MetaAdapterFactory.getConcept(MetaAdapterFactory.getLanguage(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, "jetbrains.mps.baseLanguage"), 0xf8c77f1e98L, "VariableReference"), null, null, false);
SNodeAccessUtil.setReferenceTarget(quotedNode_2, MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, 0xf8cc6bf960L, "variableDeclaration"), (SNode) parameter_1);
return quotedNode_2;
}
}