/* * Copyright 2003-2016 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.ide; import com.intellij.configurationStore.StoreAwareProjectManager; import jetbrains.mps.ide.newSolutionDialog.NewModuleUtil; import jetbrains.mps.module.ModuleDeleteHelper; import jetbrains.mps.project.AbstractModule; import jetbrains.mps.project.DescriptorTargetFileAlreadyExistsException; import jetbrains.mps.project.DevKit; import jetbrains.mps.project.Solution; import jetbrains.mps.refactoring.Renamer; import jetbrains.mps.smodel.Generator; import jetbrains.mps.smodel.Language; import jetbrains.mps.util.Reference; import jetbrains.mps.vfs.CachingFile; import jetbrains.mps.vfs.DefaultCachingContext; import jetbrains.mps.vfs.IFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.mps.openapi.module.SModule; import org.junit.Assert; import org.junit.Test; import java.util.Collection; import java.util.Collections; import java.util.List; /** * Tests for Rename and Delete actions. * Also checks some elementary vfs changes. * Note: several {@link #invokeInCommand(Runnable)} calls * are needed because of the absent undo realisation for the 'create module' actions. * * Also {@link StoreAwareProjectManager#flushChangedAlarm()} requires zero-level command */ public class ModuleIDETests extends ModuleInProjectTest { private void checkGenerators(@NotNull Language language) { Collection<Generator> generators = language.getGenerators(); Assert.assertTrue(ourProject.getProjectModules().contains(language)); Assert.assertTrue(ourProject.getProjectModulesWithGenerators().containsAll(generators)); generators.forEach(g -> Assert.assertFalse(ourProject.getProjectModules().contains(g))); } @Test public void createSolution() { String solutionName = getNewModuleName(); Reference<Solution> solutionRef = new Reference<>(); invokeInCommand(() -> solutionRef.set(NewModuleUtil.createSolution(solutionName, createNewDirInProject(), ModuleIDETests.ourProject))); invokeInCommand(() -> { Solution solution = solutionRef.get(); Assert.assertNotNull(solution.getRepository()); Assert.assertEquals(solutionName, solution.getModuleName()); Assert.assertTrue(ModuleIDETests.ourProject.getProjectModules().contains(solution)); }); } @Test public void createLanguage() { String langName = getNewModuleName(); Reference<Language> langRef = new Reference<>(); invokeInCommand(() -> langRef.set(NewModuleUtil.createLanguage(langName, createNewDirInProject(), ModuleIDETests.ourProject))); invokeInCommand(() -> { Language language = langRef.get(); Assert.assertNotNull(language.getRepository()); Assert.assertEquals(langName, language.getModuleName()); Assert.assertTrue(ModuleIDETests.ourProject.getProjectModules().contains(language)); checkGenerators(language); }); } @Test public void createDevkit() { String devkitName = getNewModuleName(); Reference<DevKit> devkitRef = new Reference<>(); invokeInCommand(() -> devkitRef.set(NewModuleUtil.createDevKit(devkitName, createNewDirInProject(), ourProject))); invokeInCommand(() -> { DevKit devkit = devkitRef.get(); Assert.assertNotNull(devkit.getRepository()); Assert.assertEquals(devkitName, devkit.getModuleName()); Assert.assertTrue(ourProject.getProjectModules().contains(devkit)); }); } @Test public void renameModule() { String moduleName = getNewModuleName(); String newModuleName = getNewModuleName(); Reference<Language> langRef = new Reference<>(); invokeInCommand(() -> langRef.set(NewModuleUtil.createLanguage(moduleName, createNewDirInProject(), ourProject))); invokeInCommand(() -> { Language lang = langRef.get(); try { Renamer.renameModule(lang, newModuleName); } catch (DescriptorTargetFileAlreadyExistsException e) { throw new RuntimeException(e); } Assert.assertEquals(newModuleName, lang.getModuleName()); IFile descriptorFile = lang.getDescriptorFile(); Assert.assertNotNull(descriptorFile); String fileName = descriptorFile.toPath().getFileName(); Assert.assertNotNull(fileName); Assert.assertTrue(fileName.contains(newModuleName)); }); } @Test public void deleteModule() { String moduleName = getNewModuleName(); Reference<Language> langRef = new Reference<>(); invokeInCommand(() -> langRef.set(NewModuleUtil.createLanguage(moduleName, createNewDirInProject(), ourProject))); invokeInCommand(() -> { @NotNull Language lang = langRef.get(); deleteModule(lang, false); CachingFile descriptorFile = (CachingFile) lang.getDescriptorFile(); Assert.assertNotNull(descriptorFile); descriptorFile.refresh(new DefaultCachingContext(true, false)); Assert.assertTrue(descriptorFile.exists()); Assert.assertFalse(ourProject.getProjectModules().contains(lang)); }); } @Test public void deleteModuleWithFiles() { String moduleName = getNewModuleName(); Reference<Language> langRef = new Reference<>(); invokeInCommand(() -> langRef.set(NewModuleUtil.createLanguage(moduleName, createNewDirInProject(), ourProject))); invokeInCommand(() -> { @NotNull Language lang = langRef.get(); deleteModule(lang, true); CachingFile moduleSourceDir = (CachingFile) lang.getModuleSourceDir(); Assert.assertNotNull(moduleSourceDir); moduleSourceDir.refresh(new DefaultCachingContext(true, true)); Assert.assertFalse(moduleSourceDir.exists()); Assert.assertFalse(ourProject.getProjectModules().contains(lang)); }); } @Test public void deleteRenamedLanguage() { deleteRenamedLang(true); } @Test public void deleteWithFilesRenamedLanguage() { deleteRenamedLang(false); } private void deleteRenamedLang(boolean deleteFiles) { String moduleName = getNewModuleName(); String newModuleName = getNewModuleName(); Reference<Language> langRef = new Reference<>(); invokeInCommand(() -> langRef.set(NewModuleUtil.createLanguage(moduleName, createNewDirInProject(), ourProject))); invokeInCommand(() -> { @NotNull Language lang = langRef.get(); try { Renamer.renameModule(lang, newModuleName); } catch (DescriptorTargetFileAlreadyExistsException e) { throw new RuntimeException(e); } deleteModule(lang, deleteFiles); CachingFile descriptorFile = (CachingFile) lang.getDescriptorFile(); Assert.assertNotNull(descriptorFile); descriptorFile.refresh(new DefaultCachingContext(true, false)); Assert.assertTrue(deleteFiles ^ descriptorFile.exists()); Assert.assertFalse(ourProject.getProjectModules().contains(lang)); }); } @Test public void revertRenamedModule() { String oldModuleName = getNewModuleName(); String newModuleName = getNewModuleName(); ProjectBackup projectBackup = new ProjectBackup(ourProject); Reference<Language> langRef = new Reference<>(); invokeInCommand(() -> langRef.set(NewModuleUtil.createLanguage(oldModuleName, createNewDirInProject(), ourProject))); invokeInCommand(() -> { @NotNull Language lang = langRef.get(); saveProjectInTest(); projectBackup.doBackup(); try { Renamer.renameModule(lang, newModuleName); } catch (DescriptorTargetFileAlreadyExistsException e) { throw new RuntimeException(e); } Assert.assertEquals(lang.getModuleName(), newModuleName); Assert.assertTrue(ourProject.getProjectModules().contains(lang)); }); invokeInCommand(() -> { saveProjectInTest(); projectBackup.restoreFromBackup(); }); refreshProjectRecursively(); invokeInCommand(() -> { @NotNull Language lang = langRef.get(); List<SModule> projectModules = ourProject.getProjectModules(); Assert.assertTrue(projectModules.size() == 1); Assert.assertNotEquals("The old language must have been unregistered", lang, projectModules.get(0)); Assert.assertNull(lang.getRepository()); lang = (Language) projectModules.get(0); // the module is changed when MPSProject#update is called (like in this case) Assert.assertEquals(lang.getModuleName(), oldModuleName); }); } @Test public void revertDeletedModule() { revertDeletedModule0(false); } @Test public void revertDeletedWithFilesModule() { revertDeletedModule0(true); } private void revertDeletedModule0(boolean deleteFiles) { String moduleName = getNewModuleName(); ProjectBackup projectBackup = new ProjectBackup(ourProject); Reference<Language> langRef = new Reference<>(); invokeInCommand(() -> langRef.set(NewModuleUtil.createLanguage(moduleName, createNewDirInProject(), ourProject))); invokeInCommand(() -> { @NotNull Language lang = langRef.get(); saveProjectInTest(); projectBackup.doBackup(); deleteModule(lang, deleteFiles); Assert.assertFalse(deleteFiles && lang.getDescriptorFile().exists()); Assert.assertTrue(ourProject.getProjectModules().isEmpty()); }); invokeInCommand(() -> { saveProjectInTest(); projectBackup.restoreFromBackup(); }); refreshProjectRecursively(); invokeInCommand(() -> { @NotNull Language lang = langRef.get(); Assert.assertTrue(ourProject.getProjectModules().size() == 1); Assert.assertTrue(lang.getDescriptorFile().exists()); lang = (Language) ourProject.getProjectModules().get(0); // the module is changed when SMPSProject#update is called (like in this case) Assert.assertEquals(lang.getModuleName(), moduleName); }); } private void deleteModule(AbstractModule lang, boolean deleteFiles) { new ModuleDeleteHelper(ourProject).deleteModules(Collections.singletonList(lang), false, deleteFiles); } }