blob: 72bbff443dfa5a13d7fcea6c7c6ea06323008478 [file] [log] [blame]
/*
* Copyright 2000-2014 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 com.intellij.testFramework.fixtures.impl;
import com.intellij.ide.IdeView;
import com.intellij.ide.highlighter.ProjectFileType;
import com.intellij.ide.startup.impl.StartupManagerImpl;
import com.intellij.idea.IdeaTestApplication;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.fileTypes.impl.FileTypeManagerImpl;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ex.ProjectManagerEx;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.encoding.EncodingManager;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageManagerImpl;
import com.intellij.testFramework.EditorListenerTracker;
import com.intellij.testFramework.LightPlatformTestCase;
import com.intellij.testFramework.PlatformTestCase;
import com.intellij.testFramework.ThreadTracker;
import com.intellij.testFramework.builders.ModuleFixtureBuilder;
import com.intellij.testFramework.fixtures.HeavyIdeaTestFixture;
import com.intellij.util.PathUtil;
import com.intellij.util.ui.UIUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.util.HashSet;
import java.util.Set;
/**
* Creates new project for each test.
* @author mike
*/
class HeavyIdeaTestFixtureImpl extends BaseFixture implements HeavyIdeaTestFixture {
@NonNls private static final String PROJECT_FILE_SUFFIX = ProjectFileType.DOT_DEFAULT_EXTENSION;
private Project myProject;
private final Set<File> myFilesToDelete = new HashSet<File>();
private IdeaTestApplication myApplication;
private final Set<ModuleFixtureBuilder> myModuleFixtureBuilders = new THashSet<ModuleFixtureBuilder>();
private EditorListenerTracker myEditorListenerTracker;
private ThreadTracker myThreadTracker;
private final String myName;
public HeavyIdeaTestFixtureImpl(@NotNull String name) {
myName = name;
}
protected void addModuleFixtureBuilder(ModuleFixtureBuilder builder) {
myModuleFixtureBuilders.add(builder);
}
@Override
public void setUp() throws Exception {
super.setUp();
initApplication();
setUpProject();
EncodingManager.getInstance(); // adds listeners
myEditorListenerTracker = new EditorListenerTracker();
myThreadTracker = new ThreadTracker();
InjectedLanguageManagerImpl.pushInjectors(getProject());
}
@Override
public void tearDown() throws Exception {
Project project = getProject();
LightPlatformTestCase.doTearDown(project, myApplication, false);
for (ModuleFixtureBuilder moduleFixtureBuilder : myModuleFixtureBuilders) {
moduleFixtureBuilder.getFixture().tearDown();
}
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
Disposer.dispose(myProject);
myProject = null;
}
});
}
});
for (final File fileToDelete : myFilesToDelete) {
boolean deleted = FileUtil.delete(fileToDelete);
assert deleted : "Can't delete " + fileToDelete;
}
super.tearDown();
myEditorListenerTracker.checkListenersLeak();
myThreadTracker.checkLeak();
LightPlatformTestCase.checkEditorsReleased();
PlatformTestCase.cleanupApplicationCaches(project);
InjectedLanguageManagerImpl.checkInjectorsAreDisposed(project);
}
private void setUpProject() throws Exception {
new WriteCommandAction.Simple(null) {
@Override
protected void run() throws Throwable {
File tempDirectory = FileUtil.createTempDirectory(myName, "");
File projectFile = new File(tempDirectory, myName + PROJECT_FILE_SUFFIX);
myFilesToDelete.add(tempDirectory);
LocalFileSystem.getInstance().refreshAndFindFileByIoFile(projectFile);
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
new Throwable(projectFile.getPath()).printStackTrace(new PrintStream(buffer));
myProject = PlatformTestCase.createProject(projectFile, buffer.toString());
for (ModuleFixtureBuilder moduleFixtureBuilder: myModuleFixtureBuilders) {
moduleFixtureBuilder.getFixture().setUp();
}
StartupManagerImpl sm = (StartupManagerImpl)StartupManager.getInstance(myProject);
sm.runStartupActivities();
sm.startCacheUpdate();
sm.runPostStartupActivities();
ProjectManagerEx.getInstanceEx().openTestProject(myProject);
LightPlatformTestCase.clearUncommittedDocuments(myProject);
((FileTypeManagerImpl)FileTypeManager.getInstance()).drainReDetectQueue();
}
}.execute().throwException();
}
private void initApplication() throws Exception {
myApplication = IdeaTestApplication.getInstance(null);
myApplication.setDataProvider(new MyDataProvider());
}
@Override
public Project getProject() {
assert myProject != null : "setUp() should be called first";
return myProject;
}
@Override
public Module getModule() {
Module[] modules = ModuleManager.getInstance(getProject()).getModules();
return modules.length == 0 ? null : modules[0];
}
private class MyDataProvider implements DataProvider {
@Override
@Nullable
public Object getData(@NonNls String dataId) {
if (CommonDataKeys.PROJECT.is(dataId)) {
return myProject;
}
else if (CommonDataKeys.EDITOR.is(dataId) || OpenFileDescriptor.NAVIGATE_IN_EDITOR.is(dataId)) {
if (myProject == null) return null;
return FileEditorManager.getInstance(myProject).getSelectedTextEditor();
}
else {
Editor editor = (Editor)getData(CommonDataKeys.EDITOR.getName());
if (editor != null) {
FileEditorManagerEx manager = FileEditorManagerEx.getInstanceEx(myProject);
return manager.getData(dataId, editor, editor.getCaretModel().getCurrentCaret());
}
else if (LangDataKeys.IDE_VIEW.is(dataId)) {
VirtualFile[] contentRoots = ProjectRootManager.getInstance(myProject).getContentRoots();
final PsiDirectory psiDirectory = PsiManager.getInstance(myProject).findDirectory(contentRoots[0]);
if (contentRoots.length > 0) {
return new IdeView() {
@Override
public void selectElement(PsiElement element) {
}
@NotNull
@Override
public PsiDirectory[] getDirectories() {
return new PsiDirectory[] {psiDirectory};
}
@Override
public PsiDirectory getOrChooseDirectory() {
return psiDirectory;
}
};
}
}
return null;
}
}
}
@Override
public PsiFile addFileToProject(@NotNull @NonNls String rootPath, @NotNull @NonNls final String relativePath, @NotNull @NonNls final String fileText) throws IOException {
final VirtualFile dir = VfsUtil.createDirectories(rootPath + "/" + PathUtil.getParentPath(relativePath));
final VirtualFile[] virtualFile = new VirtualFile[1];
new WriteCommandAction.Simple(getProject()) {
@Override
protected void run() throws Throwable {
virtualFile[0] = dir.createChildData(this, StringUtil.getShortName(relativePath, '/'));
VfsUtil.saveText(virtualFile[0], fileText);
}
}.execute();
return ApplicationManager.getApplication().runReadAction(new Computable<PsiFile>() {
@Override
public PsiFile compute() {
return PsiManager.getInstance(getProject()).findFile(virtualFile[0]);
}
});
}
}