/* * Copyright 2003-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jetbrains.mps.idea.core.refactoring; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiPackage; import com.intellij.refactoring.listeners.RefactoringElementListener; import com.intellij.refactoring.listeners.RefactoringElementListenerProvider; import jetbrains.mps.ide.project.ProjectHelper; import jetbrains.mps.ide.vfs.VirtualFileUtils; import jetbrains.mps.smodel.SModelFileTracker; import jetbrains.mps.vfs.IFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.mps.openapi.model.EditableSModel; import org.jetbrains.mps.openapi.model.SModel; import java.util.ArrayList; import java.util.List; /** * This class listens to package rename refactorings and if there are models in the directories * of the package then it renames them. * It works for file-per-root persisted models under java packages. * So it currently assumes that if a model lives in the package dir according to SModelFileTracker * then its name is really derived from the package and should be maintained when the package is renamed. * * Created by danilla on 2/12/15. */ public class PackageRenameListener implements RefactoringElementListenerProvider { @Nullable @Override public RefactoringElementListener getListener(PsiElement element) { if (!(element instanceof PsiPackage)) { return null; } final PsiPackage pkg = (PsiPackage) element; // collecting models whose source is one of the package dirs final List<SModel> models = new ArrayList<SModel>(); for (PsiDirectory psiDir : pkg.getDirectories()) { IFile iFile = VirtualFileUtils.toIFile(psiDir.getVirtualFile()); SModel model = SModelFileTracker.getInstance(ProjectHelper.getProjectRepository(element.getProject())).findModel(iFile); if (model != null) { models.add(model); } } return new RefactoringElementListener() { boolean handled = false; @Override public void elementMoved(@NotNull PsiElement newElement) { } @Override public void elementRenamed(@NotNull final PsiElement newElement) { // for some reason this method is called twice for each rename if (!handled) { // we already hold idea write action // let's take mps write action to be able to do rename ProjectHelper.getModelAccess(newElement.getProject()).executeCommand(new Runnable() { public void run() { String newName = ((PsiPackage) newElement).getQualifiedName(); // renaming for (SModel model : models) { if (!(model instanceof EditableSModel)) { return; } ((EditableSModel) model).rename(newName, false); // todo update refs to this model (may not be strictly necessary) } } }); handled = true; } } }; } }