package jetbrains.mps.refactoring.framework; /*Generated by MPS */ import org.apache.log4j.Logger; import org.apache.log4j.LogManager; import java.util.List; import java.util.ArrayList; import jetbrains.mps.smodel.Language; import jetbrains.mps.smodel.ModuleRepositoryFacade; import java.util.Set; import java.util.HashSet; import org.jetbrains.mps.openapi.model.SModel; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModuleOperations; import jetbrains.mps.util.SNodeOperations; import org.jetbrains.mps.openapi.model.SNode; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModelOperations; import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations; import org.apache.log4j.Level; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.Collection; import java.util.Arrays; public class RefactoringUtil { private static final Logger LOG_1635700302 = LogManager.getLogger(RefactoringUtil.class); private static final Logger LOG = LogManager.getLogger(RefactoringUtil.class); public RefactoringUtil() { } public static IRefactoring getRefactoringByClassName(String className) { for (IRefactoring r : RefactoringUtil.getAllRefactorings()) { Class refClass = r.getClass(); if (refClass.getName().equals(className)) { return r; } } return null; } public static List<IRefactoring> getAllRefactorings() { List<IRefactoring> allRefactorings = new ArrayList<IRefactoring>(); for (Language language : ModuleRepositoryFacade.getInstance().getAllModules(Language.class)) { allRefactorings.addAll(RefactoringUtil.getRefactorings(language)); } return allRefactorings; } public static Set<IRefactoring> getRefactorings(Language language) { Set<IRefactoring> result = new HashSet<IRefactoring>(); SModel refModelDescriptor = SModuleOperations.getAspect(language, "refactorings"); if (refModelDescriptor != null) { SModel refactoringsModel = refModelDescriptor; String packageName = SNodeOperations.getModelLongName(refactoringsModel); for (SNode refactoring : SModelOperations.roots(refactoringsModel, MetaAdapterFactory.getConcept(0x3ecd7c84cde345deL, 0x886c135ecc69b742L, 0x5fb04b74a778e245L, "jetbrains.mps.lang.refactoring.structure.Refactoring"))) { try { String fqName = packageName + "." + SPropertyOperations.getString(refactoring, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name")); Class<IRefactoring> cls = null; try { cls = ((Class<IRefactoring>) language.getOwnClass(fqName)); } catch (ClassNotFoundException e) { // Class not found - refactoring is not available now } if (cls == null) { if (LOG_1635700302.isEnabledFor(Level.WARN)) { LOG_1635700302.warn("Can't find class " + fqName + " for refactoring. Refactoring disabled."); } continue; } Constructor<IRefactoring> constructor = cls.getConstructor(); constructor.setAccessible(false); result.add(constructor.newInstance()); } catch (InstantiationException e) { if (LOG_1635700302.isEnabledFor(Level.ERROR)) { LOG_1635700302.error("", e); } } catch (InvocationTargetException e) { if (LOG_1635700302.isEnabledFor(Level.ERROR)) { LOG_1635700302.error("", e); } } catch (IllegalAccessException e) { if (LOG_1635700302.isEnabledFor(Level.ERROR)) { LOG_1635700302.error("", e); } } catch (NoSuchMethodException e) { if (LOG_1635700302.isEnabledFor(Level.ERROR)) { LOG_1635700302.error("", e); } } } } return result; } public static RefactoringUtil.Applicability getApplicability(IRefactoring refactoring, Collection entities) { assert !(entities.isEmpty()); assert (entities.size() == 1 || refactoring.getRefactoringTarget().allowMultipleTargets()); IRefactoringTarget target = refactoring.getRefactoringTarget(); if (!(RefactoringUtil.isApplicableToEntities(refactoring.getUserFriendlyName(), target, entities))) { return RefactoringUtil.Applicability.NOT_APPLICABLE; } for (IRefactoring r : RefactoringUtil.getAllRefactorings()) { if (r.getOverridenRefactoringClass() == null) { continue; } if (r.getRefactoringTarget().getTarget() != target.getTarget()) { continue; } if (!(RefactoringUtil.isApplicableToEntities(r.getUserFriendlyName(), r.getRefactoringTarget(), entities))) { continue; } Class refClass = refactoring.getClass(); if (r.getOverridenRefactoringClass() == null) { continue; } if (r.getOverridenRefactoringClass() == refClass) { return RefactoringUtil.Applicability.OVERRIDDEN; } String overriddenName = r.getOverridenRefactoringClass().getName(); String refClassName = refClass.getName(); String overriddenClassLoader = r.getOverridenRefactoringClass().getClassLoader().toString(); String refClassLoader = refClass.getClassLoader().toString(); assert !(overriddenName.equals(refClassName)) : "Refactoring classes are loaded using different classloaders. overridden: " + overriddenClassLoader + "; " + "ref: " + refClassLoader + "; class: " + refClassName; } return RefactoringUtil.Applicability.APPLICABLE; } private static boolean isApplicableToEntities(String refactoringName, IRefactoringTarget target, Collection entities) { if (!(target.allowMultipleTargets()) && entities.size() > 1) { return false; } for (Object entity : entities) { boolean applicable; try { applicable = target.isApplicable(entity); } catch (Throwable t) { if (LOG_1635700302.isEnabledFor(Level.ERROR)) { LOG_1635700302.error("An error occured while executing " + refactoringName + ".isApplicable(). This refactoring will not be available.", t); } applicable = false; } if (!(applicable)) { return false; } } return true; } public static boolean isApplicable(IRefactoring refactoring, Object target) { IRefactoringTarget refTarget = refactoring.getRefactoringTarget(); boolean oneEntity = !(refTarget.allowMultipleTargets()); List targetList; if (!(oneEntity)) { targetList = ((List) target); } else { targetList = Arrays.asList(target); } boolean disabled = (targetList.isEmpty() || RefactoringUtil.getApplicability(refactoring, targetList).lessThan(RefactoringUtil.Applicability.APPLICABLE)); return !(disabled); } public enum Applicability { APPLICABLE() { public boolean lessThan(RefactoringUtil.Applicability level) { return false; } }, NOT_APPLICABLE() { public boolean lessThan(RefactoringUtil.Applicability level) { return true; } }, OVERRIDDEN() { public boolean lessThan(RefactoringUtil.Applicability level) { return level == RefactoringUtil.Applicability.APPLICABLE; } }; private Applicability() { } public abstract boolean lessThan(RefactoringUtil.Applicability level); } }