/* * 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.tests; import com.intellij.facet.FacetManager; import com.intellij.facet.FacetType; import com.intellij.facet.FacetTypeRegistry; import com.intellij.facet.ModifiableFacetModel; import com.intellij.ide.highlighter.ModuleFileType; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.module.StdModuleTypes; import com.intellij.openapi.project.Project; import com.intellij.testFramework.PlatformTestUtil; import com.intellij.testFramework.UsefulTestCase; import com.intellij.testFramework.builders.JavaModuleFixtureBuilder; import com.intellij.testFramework.fixtures.IdeaProjectTestFixture; import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory; import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture; import com.intellij.testFramework.fixtures.JavaTestFixtureFactory; import com.intellij.testFramework.fixtures.TestFixtureBuilder; import com.intellij.testFramework.fixtures.impl.JavaTestFixtureFactoryImpl; import com.intellij.util.PathUtil; import com.intellij.util.ThrowableRunnable; import com.intellij.util.ui.UIUtil; import jetbrains.mps.ide.project.ProjectHelper; import jetbrains.mps.idea.core.facet.MPSFacet; import jetbrains.mps.idea.core.facet.MPSFacetConfiguration; import jetbrains.mps.idea.core.facet.MPSFacetType; import jetbrains.mps.smodel.ModelAccess; import jetbrains.mps.smodel.ModelAccessHelper; import jetbrains.mps.util.Computable; import org.jetbrains.annotations.NotNull; import javax.swing.SwingUtilities; import java.io.File; public abstract class AbstractMPSFixtureTestCase extends UsefulTestCase { private static int ourIndex = 0; protected MPSFacet myFacet; protected JavaCodeInsightTestFixture myFixture; protected Module myModule; protected TestFixtureBuilder<IdeaProjectTestFixture> myProjectBuilder; static { IdeaTestFixtureFactory.getFixtureFactory().registerFixtureBuilder(CustomJavaModuleFixtureBuilder.class, CustomJavaModuleFixtureBuilder.class); } private static int getNextIndex() { return ourIndex++; } public static void flushEDT() throws InterruptedException { assert SwingUtilities.isEventDispatchThread(); final boolean[] flag = new boolean[]{false}; // fixme use ApplicationManager.getApplication().invokeLater() ? ModelAccess.instance().runReadInEDT(() -> flag[0] = true); while (!flag[0]) { PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue(); } } @Override protected void setUp() throws Exception { super.setUp(); // was copied from JavaCodeInsightFixtureTestCase // we can remove these lines and extend from JavaCodeInsightFixtureTestCase in IDEA 11. myProjectBuilder = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(getName()); myFixture = JavaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(myProjectBuilder.getFixture()); final JavaModuleFixtureBuilder moduleFixtureBuilder = myProjectBuilder.addModule(CustomJavaModuleFixtureBuilder.class); moduleFixtureBuilder.addSourceContentRoot(myFixture.getTempDirPath()); tuneFixture(moduleFixtureBuilder); myFixture.setUp(); myFixture.setTestDataPath(getTestDataPath()); myModule = moduleFixtureBuilder.getFixture().getModule(); myFacet = addMPSFacet(myModule); //Flush all EDT events to be made before run tests try { UIUtil.invokeAndWaitIfNeeded(new ThrowableRunnable() { @Override public void run() throws Throwable { flushEDT(); } }); } catch (Throwable throwable) { Logger.getInstance(this.getClass()).error("Error while flushing EDT events", throwable); } } @Override protected void tearDown() throws Exception { if (!ApplicationManager.getApplication().isDispatchThread()) { // fixme needed at all? another way? maybe flushEDT() ModelAccess.instance().flushEventQueue(); } myModule = null; try { myFixture.tearDown(); } finally { myFixture = null; super.tearDown(); } } protected Module addModuleAndSetupFixture(TestFixtureBuilder<IdeaProjectTestFixture> projectBuilder) throws Exception { CustomJavaModuleFixtureBuilder moduleFixtureBuilder = projectBuilder.addModule(CustomJavaModuleFixtureBuilder.class); moduleFixtureBuilder.getFixture().setUp(); String moduleFolderName = "module" + getNextIndex(); File moduleFolder = new File(myFixture.getTempDirPath() + File.separator + moduleFolderName); assertTrue(moduleFolder.mkdirs()); moduleFixtureBuilder.setModuleFolderName(moduleFolderName); moduleFixtureBuilder.addSourceContentRoot(moduleFolder.getPath()); return moduleFixtureBuilder.getFixture().getModule(); } protected String getModuleHome() { return PathUtil.getParentPath(myModule.getModuleFilePath()); } protected void tuneFixture(final JavaModuleFixtureBuilder moduleBuilder) throws Exception { } protected String getTestDataPath() { return PathManager.getHomePath().replace(File.separatorChar, '/') + getBasePath(); } protected String getBasePath() { return ""; } protected MPSFacet addMPSFacet(Module module) { final FacetManager facetManager = FacetManager.getInstance(module); FacetType<MPSFacet, MPSFacetConfiguration> facetType = FacetTypeRegistry.getInstance().findFacetType(MPSFacetType.ID); assertNotNull("MPS facet type is not found", facetType); final MPSFacet facet = facetManager.createFacet(facetType, "MPS", null); final MPSFacetConfiguration configuration = facet.getConfiguration(); final ModifiableFacetModel facetModel = facetManager.createModifiableModel(); facetModel.addFacet(facet); UIUtil.invokeAndWaitIfNeeded(new Runnable() { @Override public void run() { preConfigureFacet(configuration); final ModifiableFacetModel facetModel = facetManager.createModifiableModel(); facetModel.addFacet(facet); ApplicationManager.getApplication().runWriteAction(facetModel::commit); } }); return facet; } protected void preConfigureFacet(MPSFacetConfiguration configuration) { } /** * Execute Runnable with MPS read lock */ protected final void runModelRead(@NotNull Runnable r) { jetbrains.mps.project.Project mpsProject = ProjectHelper.fromIdeaProject((myModule.getProject())); mpsProject.getModelAccess().runReadAction(r); } protected final <T> T runModelRead(@NotNull Computable<T> c) { return new ModelAccessHelper(ProjectHelper.getModelAccess(myModule.getProject())).runReadAction(c); } public static class CustomJavaModuleFixtureBuilder extends JavaTestFixtureFactoryImpl.MyJavaModuleFixtureBuilderImpl { private static int ourIndex; private String myModuleFolderName; public CustomJavaModuleFixtureBuilder(TestFixtureBuilder<? extends IdeaProjectTestFixture> testFixtureBuilder) { super(testFixtureBuilder); } protected Module createModule() { IdeaProjectTestFixture fixture = (IdeaProjectTestFixture) myFixtureBuilder.getFixture(); final Project project = fixture.getProject(); assert project != null; final String moduleFilePath = new File(project.getProjectFilePath()).getParent() + File.separator + getModuleFileName(); return ModuleManager.getInstance(project).newModule(moduleFilePath, StdModuleTypes.JAVA.getId()); } private static int getNextIndex() { return ourIndex++; } private String getModuleFileName() { return (myModuleFolderName == null ? getNextIndex() : myModuleFolderName + File.separator + myModuleFolderName) + ModuleFileType.DOT_DEFAULT_EXTENSION; } public void setModuleFolderName(String moduleFolderName) { myModuleFolderName = moduleFolderName; } } }