| /* |
| * 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; |
| |
| import com.intellij.ProjectTopics; |
| import com.intellij.codeHighlighting.HighlightDisplayLevel; |
| import com.intellij.codeInsight.completion.CompletionProgressIndicator; |
| import com.intellij.codeInsight.daemon.HighlightDisplayKey; |
| import com.intellij.codeInsight.hint.HintManager; |
| import com.intellij.codeInsight.hint.HintManagerImpl; |
| import com.intellij.codeInsight.lookup.LookupManager; |
| import com.intellij.codeInspection.InspectionEP; |
| import com.intellij.codeInspection.InspectionProfileEntry; |
| import com.intellij.codeInspection.LocalInspectionEP; |
| import com.intellij.codeInspection.LocalInspectionTool; |
| import com.intellij.codeInspection.ex.*; |
| import com.intellij.ide.highlighter.ProjectFileType; |
| import com.intellij.ide.startup.StartupManagerEx; |
| import com.intellij.ide.startup.impl.StartupManagerImpl; |
| import com.intellij.idea.IdeaLogger; |
| import com.intellij.idea.IdeaTestApplication; |
| import com.intellij.openapi.actionSystem.CommonDataKeys; |
| import com.intellij.openapi.actionSystem.DataProvider; |
| import com.intellij.openapi.application.Application; |
| import com.intellij.openapi.application.ApplicationManager; |
| import com.intellij.openapi.application.ex.ApplicationEx; |
| import com.intellij.openapi.application.impl.ApplicationInfoImpl; |
| import com.intellij.openapi.command.WriteCommandAction; |
| import com.intellij.openapi.command.impl.UndoManagerImpl; |
| import com.intellij.openapi.command.undo.UndoManager; |
| import com.intellij.openapi.editor.Document; |
| import com.intellij.openapi.editor.Editor; |
| import com.intellij.openapi.editor.EditorFactory; |
| import com.intellij.openapi.editor.impl.EditorFactoryImpl; |
| import com.intellij.openapi.editor.impl.EditorImpl; |
| import com.intellij.openapi.extensions.Extensions; |
| import com.intellij.openapi.fileEditor.FileDocumentManager; |
| import com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl; |
| import com.intellij.openapi.fileTypes.FileType; |
| import com.intellij.openapi.fileTypes.FileTypeManager; |
| import com.intellij.openapi.fileTypes.impl.FileTypeManagerImpl; |
| import com.intellij.openapi.module.EmptyModuleType; |
| import com.intellij.openapi.module.Module; |
| import com.intellij.openapi.module.ModuleManager; |
| import com.intellij.openapi.module.ModuleType; |
| import com.intellij.openapi.project.ModuleAdapter; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.project.ProjectManager; |
| import com.intellij.openapi.project.ex.ProjectEx; |
| import com.intellij.openapi.project.ex.ProjectManagerEx; |
| import com.intellij.openapi.project.impl.ProjectImpl; |
| import com.intellij.openapi.project.impl.ProjectManagerImpl; |
| import com.intellij.openapi.projectRoots.Sdk; |
| import com.intellij.openapi.roots.*; |
| import com.intellij.openapi.startup.StartupManager; |
| import com.intellij.openapi.util.Computable; |
| import com.intellij.openapi.util.Disposer; |
| import com.intellij.openapi.util.EmptyRunnable; |
| import com.intellij.openapi.util.ShutDownTracker; |
| import com.intellij.openapi.util.io.FileUtil; |
| import com.intellij.openapi.util.text.StringUtil; |
| import com.intellij.openapi.vfs.*; |
| import com.intellij.openapi.vfs.encoding.EncodingManager; |
| import com.intellij.openapi.vfs.encoding.EncodingManagerImpl; |
| import com.intellij.openapi.vfs.ex.temp.TempFileSystem; |
| import com.intellij.openapi.vfs.impl.VirtualFilePointerManagerImpl; |
| import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS; |
| import com.intellij.openapi.vfs.newvfs.persistent.PersistentFSImpl; |
| import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager; |
| import com.intellij.profile.codeInspection.InspectionProfileManager; |
| import com.intellij.profile.codeInspection.InspectionProjectProfileManager; |
| import com.intellij.psi.*; |
| import com.intellij.psi.codeStyle.CodeStyleSchemes; |
| import com.intellij.psi.codeStyle.CodeStyleSettings; |
| import com.intellij.psi.codeStyle.CodeStyleSettingsManager; |
| import com.intellij.psi.impl.DocumentCommitThread; |
| import com.intellij.psi.impl.PsiDocumentManagerImpl; |
| import com.intellij.psi.impl.PsiManagerImpl; |
| import com.intellij.psi.impl.source.tree.injected.InjectedLanguageManagerImpl; |
| import com.intellij.psi.templateLanguages.TemplateDataLanguageMappings; |
| import com.intellij.util.Consumer; |
| import com.intellij.util.IncorrectOperationException; |
| import com.intellij.util.LocalTimeCounter; |
| import com.intellij.util.containers.ContainerUtil; |
| import com.intellij.util.indexing.FileBasedIndex; |
| import com.intellij.util.indexing.IndexableFileSet; |
| import com.intellij.util.messages.MessageBusConnection; |
| import com.intellij.util.ui.UIUtil; |
| import gnu.trove.THashMap; |
| import junit.framework.TestCase; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.TestOnly; |
| |
| import javax.swing.*; |
| import java.io.ByteArrayOutputStream; |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.PrintStream; |
| import java.util.*; |
| |
| import static com.intellij.openapi.roots.ModuleRootModificationUtil.updateModel; |
| |
| /** |
| * @author yole |
| */ |
| public abstract class LightPlatformTestCase extends UsefulTestCase implements DataProvider { |
| @NonNls public static final String PROFILE = "Configurable"; |
| |
| @NonNls private static final String LIGHT_PROJECT_MARK = "Light project: "; |
| |
| private static IdeaTestApplication ourApplication; |
| protected static Project ourProject; |
| private static Module ourModule; |
| private static PsiManager ourPsiManager; |
| private static boolean ourAssertionsInTestDetected; |
| private static VirtualFile ourSourceRoot; |
| private static TestCase ourTestCase = null; |
| public static Thread ourTestThread; |
| private static LightProjectDescriptor ourProjectDescriptor; |
| private static boolean ourHaveShutdownHook; |
| |
| private final Map<String, InspectionToolWrapper> myAvailableInspectionTools = new THashMap<String, InspectionToolWrapper>(); |
| private ThreadTracker myThreadTracker; |
| |
| /** |
| * @return Project to be used in tests for example for project components retrieval. |
| */ |
| public static Project getProject() { |
| return ourProject; |
| } |
| |
| /** |
| * @return Module to be used in tests for example for module components retrieval. |
| */ |
| public static Module getModule() { |
| return ourModule; |
| } |
| |
| /** |
| * Shortcut to PsiManager.getInstance(getProject()) |
| */ |
| public static PsiManager getPsiManager() { |
| if (ourPsiManager == null) { |
| ourPsiManager = PsiManager.getInstance(ourProject); |
| } |
| return ourPsiManager; |
| } |
| |
| public static IdeaTestApplication initApplication() { |
| ourApplication = IdeaTestApplication.getInstance(null); |
| return ourApplication; |
| } |
| |
| @TestOnly |
| public static void disposeApplication() { |
| if (ourApplication != null) { |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| Disposer.dispose(ourApplication); |
| } |
| }); |
| |
| ourApplication = null; |
| } |
| } |
| |
| public static IdeaTestApplication getApplication() { |
| return ourApplication; |
| } |
| |
| protected void resetAllFields() { |
| resetClassFields(getClass()); |
| } |
| |
| private void resetClassFields(final Class<?> aClass) { |
| try { |
| UsefulTestCase.clearDeclaredFields(this, aClass); |
| } |
| catch (IllegalAccessException e) { |
| throw new RuntimeException(e); |
| } |
| |
| if (aClass == LightPlatformTestCase.class) return; |
| resetClassFields(aClass.getSuperclass()); |
| } |
| |
| private static void cleanPersistedVFSContent() { |
| ((PersistentFSImpl)PersistentFS.getInstance()).cleanPersistedContents(); |
| } |
| |
| public static boolean isLight(Project project) { |
| String creationPlace = project.getUserData(CREATION_PLACE); |
| return creationPlace != null && StringUtil.startsWith(creationPlace, LIGHT_PROJECT_MARK); |
| } |
| |
| private static void initProject(@NotNull final LightProjectDescriptor descriptor) throws Exception { |
| ourProjectDescriptor = descriptor; |
| |
| final File projectFile = FileUtil.createTempFile("light_temp_", ProjectFileType.DOT_DEFAULT_EXTENSION); |
| |
| new WriteCommandAction.Simple(null) { |
| @SuppressWarnings("AssignmentToStaticFieldFromInstanceMethod") |
| @Override |
| protected void run() throws Throwable { |
| if (ourProject != null) { |
| closeAndDeleteProject(); |
| } |
| else { |
| cleanPersistedVFSContent(); |
| } |
| |
| LocalFileSystem.getInstance().refreshAndFindFileByIoFile(projectFile); |
| |
| ByteArrayOutputStream buffer = new ByteArrayOutputStream(); |
| new Throwable(projectFile.getPath()).printStackTrace(new PrintStream(buffer)); |
| |
| ourProject = PlatformTestCase.createProject(projectFile, LIGHT_PROJECT_MARK + buffer.toString()); |
| ourPathToKeep = projectFile.getPath(); |
| if (!ourHaveShutdownHook) { |
| ourHaveShutdownHook = true; |
| registerShutdownHook(); |
| } |
| ourPsiManager = null; |
| ourModule = createMainModule(descriptor.getModuleType()); |
| |
| VirtualFile dummyRoot = VirtualFileManager.getInstance().findFileByUrl("temp:///"); |
| assert dummyRoot != null; |
| dummyRoot.refresh(false, false); |
| |
| try { |
| ourSourceRoot = dummyRoot.createChildDirectory(this, "src"); |
| cleanSourceRoot(); |
| } |
| catch (IOException e) { |
| throw new RuntimeException(e); |
| } |
| |
| FileBasedIndex.getInstance().registerIndexableSet(new IndexableFileSet() { |
| @Override |
| public boolean isInSet(@NotNull final VirtualFile file) { |
| return ourSourceRoot != null && |
| file.getFileSystem() == ourSourceRoot.getFileSystem() && |
| ourProject != null && |
| ourProject.isOpen(); |
| } |
| |
| @Override |
| public void iterateIndexableFilesIn(@NotNull final VirtualFile file, @NotNull final ContentIterator iterator) { |
| VfsUtilCore.visitChildrenRecursively(file, new VirtualFileVisitor() { |
| @Override |
| public boolean visitFile(@NotNull VirtualFile file) { |
| iterator.processFile(file); |
| return true; |
| } |
| }); |
| } |
| }, null); |
| |
| updateModel(ourModule, new Consumer<ModifiableRootModel>() { |
| @Override |
| public void consume(ModifiableRootModel model) { |
| if (descriptor.getSdk() != null) { |
| model.setSdk(descriptor.getSdk()); |
| } |
| |
| ContentEntry contentEntry = model.addContentEntry(ourSourceRoot); |
| contentEntry.addSourceFolder(ourSourceRoot, false); |
| |
| descriptor.configureModule(ourModule, model, contentEntry); |
| } |
| }); |
| |
| MessageBusConnection connection = ourProject.getMessageBus().connect(); |
| connection.subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootAdapter() { |
| @Override |
| public void beforeRootsChange(ModuleRootEvent event) { |
| /*if (!event.isCausedByFileTypesChange()) { |
| fail("Root modification in LightIdeaTestCase is not allowed."); |
| }*/ |
| } |
| }); |
| connection.subscribe(ProjectTopics.MODULES, new ModuleAdapter() { |
| @Override |
| public void moduleAdded(Project project, Module module) { |
| fail("Adding modules is not permitted in LightIdeaTestCase."); |
| } |
| }); |
| |
| StartupManagerImpl startupManager = (StartupManagerImpl)StartupManager.getInstance(ourProject); |
| startupManager.runStartupActivities(); |
| startupManager.startCacheUpdate(); |
| } |
| |
| private void cleanSourceRoot() throws IOException { |
| TempFileSystem tempFs = (TempFileSystem)ourSourceRoot.getFileSystem(); |
| for (VirtualFile child : ourSourceRoot.getChildren()) { |
| if (!tempFs.exists(child)) { |
| tempFs.createChildFile(this, ourSourceRoot, child.getName()); |
| } |
| child.delete(this); |
| } |
| } |
| }.execute().throwException(); |
| |
| // project creation may make a lot of pointers, do not regard them as leak |
| ((VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance()).storePointers(); |
| } |
| |
| protected static Module createMainModule(final ModuleType moduleType) { |
| return ApplicationManager.getApplication().runWriteAction(new Computable<Module>() { |
| @Override |
| public Module compute() { |
| return ModuleManager.getInstance(ourProject).newModule("light_idea_test_case.iml", moduleType.getId()); |
| } |
| }); |
| } |
| |
| /** |
| * @return The only source root |
| */ |
| public static VirtualFile getSourceRoot() { |
| return ourSourceRoot; |
| } |
| |
| @Override |
| protected void setUp() throws Exception { |
| UIUtil.invokeAndWaitIfNeeded(new Runnable() { |
| @Override |
| public void run() { |
| try { |
| LightPlatformTestCase.super.setUp(); |
| initApplication(); |
| ApplicationInfoImpl.setInPerformanceTest(isPerformanceTest()); |
| |
| ourApplication.setDataProvider(LightPlatformTestCase.this); |
| doSetup(new SimpleLightProjectDescriptor(getModuleType(), getProjectJDK()), configureLocalInspectionTools(), |
| myAvailableInspectionTools); |
| InjectedLanguageManagerImpl.pushInjectors(getProject()); |
| |
| storeSettings(); |
| |
| myThreadTracker = new ThreadTracker(); |
| ModuleRootManager.getInstance(ourModule).orderEntries().getAllLibrariesAndSdkClassesRoots(); |
| VirtualFilePointerManagerImpl filePointerManager = (VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance(); |
| filePointerManager.storePointers(); |
| } |
| catch (Exception e) { |
| throw new RuntimeException(e); |
| } |
| } |
| }); |
| } |
| |
| public static void doSetup(@NotNull LightProjectDescriptor descriptor, |
| @NotNull LocalInspectionTool[] localInspectionTools, |
| @NotNull final Map<String, InspectionToolWrapper> availableInspectionTools) throws Exception { |
| assertNull("Previous test " + ourTestCase + " hasn't called tearDown(). Probably overridden without super call.", ourTestCase); |
| IdeaLogger.ourErrorsOccurred = null; |
| |
| if (ourProject == null || ourProjectDescriptor == null || !ourProjectDescriptor.equals(descriptor)) { |
| initProject(descriptor); |
| } |
| ((ProjectImpl)ourProject).setTemporarilyDisposed(false); |
| |
| ProjectManagerEx projectManagerEx = ProjectManagerEx.getInstanceEx(); |
| projectManagerEx.openTestProject(ourProject); |
| |
| clearUncommittedDocuments(getProject()); |
| |
| for (LocalInspectionTool tool : localInspectionTools) { |
| enableInspectionTool(availableInspectionTools, new LocalInspectionToolWrapper(tool)); |
| } |
| |
| final InspectionProfileImpl profile = new InspectionProfileImpl(PROFILE) { |
| @Override |
| @NotNull |
| public InspectionToolWrapper[] getInspectionTools(PsiElement element) { |
| final Collection<InspectionToolWrapper> tools = availableInspectionTools.values(); |
| return tools.toArray(new InspectionToolWrapper[tools.size()]); |
| } |
| |
| @NotNull |
| @Override |
| public List<Tools> getAllEnabledInspectionTools(Project project) { |
| List<Tools> result = new ArrayList<Tools>(); |
| for (InspectionToolWrapper toolWrapper : getInspectionTools(null)) { |
| result.add(new ToolsImpl(toolWrapper, toolWrapper.getDefaultLevel(), true)); |
| } |
| return result; |
| } |
| |
| @Override |
| public boolean isToolEnabled(HighlightDisplayKey key, PsiElement element) { |
| return key != null && availableInspectionTools.containsKey(key.toString()); |
| } |
| |
| @Override |
| public HighlightDisplayLevel getErrorLevel(@NotNull HighlightDisplayKey key, PsiElement element) { |
| InspectionToolWrapper toolWrapper = availableInspectionTools.get(key.toString()); |
| return toolWrapper == null ? HighlightDisplayLevel.WARNING : toolWrapper.getDefaultLevel(); |
| } |
| |
| @Override |
| public InspectionToolWrapper getInspectionTool(@NotNull String shortName, @NotNull PsiElement element) { |
| return availableInspectionTools.get(shortName); |
| } |
| |
| @Override |
| public InspectionToolWrapper getToolById(@NotNull String id, @NotNull PsiElement element) { |
| return availableInspectionTools.get(id); |
| } |
| }; |
| final InspectionProfileManager inspectionProfileManager = InspectionProfileManager.getInstance(); |
| inspectionProfileManager.addProfile(profile); |
| inspectionProfileManager.setRootProfile(profile.getName()); |
| InspectionProjectProfileManager.getInstance(getProject()).updateProfile(profile); |
| InspectionProjectProfileManager.getInstance(getProject()).setProjectProfile(profile.getName()); |
| |
| assertFalse(getPsiManager().isDisposed()); |
| Boolean passed = null; |
| try { |
| passed = StartupManagerEx.getInstanceEx(getProject()).startupActivityPassed(); |
| } |
| catch (Exception e) { |
| |
| } |
| assertTrue("open: " + getProject().isOpen() + |
| "; disposed:" + getProject().isDisposed() + |
| "; startup passed:" + passed + |
| "; all open projects: " + Arrays.asList(ProjectManager.getInstance().getOpenProjects()), getProject().isInitialized()); |
| |
| CodeStyleSettingsManager.getInstance(getProject()).setTemporarySettings(new CodeStyleSettings()); |
| |
| final FileDocumentManager manager = FileDocumentManager.getInstance(); |
| if (manager instanceof FileDocumentManagerImpl) { |
| Document[] unsavedDocuments = manager.getUnsavedDocuments(); |
| manager.saveAllDocuments(); |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| ((FileDocumentManagerImpl)manager).dropAllUnsavedDocuments(); |
| } |
| }); |
| |
| assertEmpty("There are unsaved documents", Arrays.asList(unsavedDocuments)); |
| } |
| ((FileTypeManagerImpl)FileTypeManager.getInstance()).drainReDetectQueue(); |
| } |
| |
| // todo: use Class<? extends InspectionProfileEntry> once on Java 7 |
| protected void enableInspectionTools(@NotNull Class<?>... classes) { |
| final InspectionProfileEntry[] tools = new InspectionProfileEntry[classes.length]; |
| |
| final List<InspectionEP> eps = ContainerUtil.newArrayList(); |
| ContainerUtil.addAll(eps, Extensions.getExtensions(LocalInspectionEP.LOCAL_INSPECTION)); |
| ContainerUtil.addAll(eps, Extensions.getExtensions(InspectionEP.GLOBAL_INSPECTION)); |
| |
| next: |
| for (int i = 0; i < classes.length; i++) { |
| for (InspectionEP ep : eps) { |
| if (classes[i].getName().equals(ep.implementationClass)) { |
| tools[i] = ep.instantiateTool(); |
| continue next; |
| } |
| } |
| throw new IllegalArgumentException("Unable to find extension point for " + classes[i].getName()); |
| } |
| |
| enableInspectionTools(tools); |
| } |
| |
| protected void enableInspectionTools(@NotNull InspectionProfileEntry... tools) { |
| for (InspectionProfileEntry tool : tools) { |
| enableInspectionTool(tool); |
| } |
| } |
| |
| protected void enableInspectionTool(@NotNull InspectionToolWrapper toolWrapper) { |
| enableInspectionTool(myAvailableInspectionTools, toolWrapper); |
| } |
| protected void enableInspectionTool(@NotNull InspectionProfileEntry tool) { |
| InspectionToolWrapper toolWrapper = InspectionToolRegistrar.wrapTool(tool); |
| enableInspectionTool(myAvailableInspectionTools, toolWrapper); |
| } |
| |
| public static void enableInspectionTool(@NotNull Map<String, InspectionToolWrapper> availableLocalTools, |
| @NotNull InspectionToolWrapper toolWrapper) { |
| final String shortName = toolWrapper.getShortName(); |
| final HighlightDisplayKey key = HighlightDisplayKey.find(shortName); |
| if (key == null) { |
| String id = toolWrapper instanceof LocalInspectionToolWrapper |
| ? ((LocalInspectionToolWrapper)toolWrapper).getTool().getID() |
| : toolWrapper.getShortName(); |
| HighlightDisplayKey.register(shortName, toolWrapper.getDisplayName(), id); |
| } |
| availableLocalTools.put(shortName, toolWrapper); |
| } |
| |
| @NotNull |
| protected LocalInspectionTool[] configureLocalInspectionTools() { |
| return LocalInspectionTool.EMPTY_ARRAY; |
| } |
| |
| @Override |
| protected void tearDown() throws Exception { |
| Project project = getProject(); |
| CodeStyleSettingsManager.getInstance(project).dropTemporarySettings(); |
| @SuppressWarnings("ThrowableResultOfMethodCallIgnored") |
| CompositeException damage = checkForSettingsDamage(); |
| VirtualFilePointerManagerImpl filePointerManager = (VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance(); |
| doTearDown(project, ourApplication, true); |
| |
| try { |
| super.tearDown(); |
| } |
| finally { |
| myThreadTracker.checkLeak(); |
| InjectedLanguageManagerImpl.checkInjectorsAreDisposed(project); |
| filePointerManager.assertPointersAreDisposed(); |
| } |
| damage.throwIfNotEmpty(); |
| } |
| |
| public static void doTearDown(@NotNull final Project project, IdeaTestApplication application, boolean checkForEditors) throws Exception { |
| ((FileTypeManagerImpl)FileTypeManager.getInstance()).drainReDetectQueue(); |
| DocumentCommitThread.getInstance().clearQueue(); |
| CodeStyleSettingsManager.getInstance(project).dropTemporarySettings(); |
| checkAllTimersAreDisposed(); |
| UsefulTestCase.doPostponedFormatting(project); |
| |
| LookupManager lookupManager = LookupManager.getInstance(project); |
| if (lookupManager != null) { |
| lookupManager.hideActiveLookup(); |
| } |
| ((StartupManagerImpl)StartupManager.getInstance(project)).prepareForNextTest(); |
| InspectionProfileManager.getInstance().deleteProfile(PROFILE); |
| assertNotNull("Application components damaged", ProjectManager.getInstance()); |
| |
| new WriteCommandAction.Simple(project) { |
| @Override |
| protected void run() throws Throwable { |
| if (ourSourceRoot != null) { |
| try { |
| final VirtualFile[] children = ourSourceRoot.getChildren(); |
| for (VirtualFile child : children) { |
| child.delete(this); |
| } |
| } |
| catch (IOException e) { |
| //noinspection CallToPrintStackTrace |
| e.printStackTrace(); |
| } |
| } |
| EncodingManager encodingManager = EncodingManager.getInstance(); |
| if (encodingManager instanceof EncodingManagerImpl) ((EncodingManagerImpl)encodingManager).clearDocumentQueue(); |
| |
| FileDocumentManager manager = FileDocumentManager.getInstance(); |
| |
| ApplicationManager.getApplication().runWriteAction(EmptyRunnable.getInstance()); // Flush postponed formatting if any. |
| manager.saveAllDocuments(); |
| if (manager instanceof FileDocumentManagerImpl) { |
| ((FileDocumentManagerImpl)manager).dropAllUnsavedDocuments(); |
| } |
| } |
| }.execute().throwException(); |
| |
| assertFalse(PsiManager.getInstance(project).isDisposed()); |
| if (!ourAssertionsInTestDetected) { |
| if (IdeaLogger.ourErrorsOccurred != null) { |
| throw IdeaLogger.ourErrorsOccurred; |
| } |
| } |
| PsiDocumentManagerImpl documentManager = clearUncommittedDocuments(project); |
| ((HintManagerImpl)HintManager.getInstance()).cleanup(); |
| DocumentCommitThread.getInstance().clearQueue(); |
| |
| UIUtil.invokeAndWaitIfNeeded(new Runnable() { |
| @Override |
| public void run() { |
| ((UndoManagerImpl)UndoManager.getGlobalInstance()).dropHistoryInTests(); |
| ((UndoManagerImpl)UndoManager.getInstance(project)).dropHistoryInTests(); |
| |
| UIUtil.dispatchAllInvocationEvents(); |
| } |
| }); |
| |
| TemplateDataLanguageMappings.getInstance(project).cleanupForNextTest(); |
| |
| ProjectManagerEx.getInstanceEx().closeTestProject(project); |
| application.setDataProvider(null); |
| ourTestCase = null; |
| ((PsiManagerImpl)PsiManager.getInstance(project)).cleanupForNextTest(); |
| |
| CompletionProgressIndicator.cleanupForNextTest(); |
| |
| if (checkForEditors) { |
| checkEditorsReleased(); |
| } |
| if (isLight(project)) { |
| // mark temporarily as disposed so that rogue component trying to access it will fail |
| ((ProjectImpl)project).setTemporarilyDisposed(true); |
| documentManager.clearUncommittedDocuments(); |
| } |
| } |
| |
| public static PsiDocumentManagerImpl clearUncommittedDocuments(@NotNull Project project) { |
| PsiDocumentManagerImpl documentManager = (PsiDocumentManagerImpl)PsiDocumentManager.getInstance(project); |
| documentManager.clearUncommittedDocuments(); |
| |
| ProjectManagerImpl projectManager = (ProjectManagerImpl)ProjectManager.getInstance(); |
| if (projectManager.isDefaultProjectInitialized()) { |
| Project defaultProject = projectManager.getDefaultProject(); |
| ((PsiDocumentManagerImpl)PsiDocumentManager.getInstance(defaultProject)).clearUncommittedDocuments(); |
| } |
| return documentManager; |
| } |
| |
| public static void checkEditorsReleased() throws Exception { |
| CompositeException result = new CompositeException(); |
| final Editor[] allEditors = EditorFactory.getInstance().getAllEditors(); |
| if (allEditors.length > 0) { |
| for (Editor editor : allEditors) { |
| try { |
| EditorFactoryImpl.throwNotReleasedError(editor); |
| } |
| catch (Throwable e) { |
| result.add(e); |
| } |
| finally { |
| EditorFactory.getInstance().releaseEditor(editor); |
| } |
| } |
| try { |
| ((EditorImpl)allEditors[0]).throwDisposalError("Unreleased editors: " + allEditors.length); |
| } |
| catch (Throwable e) { |
| e.printStackTrace(); |
| result.add(e); |
| } |
| } |
| if (!result.isEmpty()) throw result; |
| } |
| |
| @Override |
| public final void runBare() throws Throwable { |
| if (!shouldRunTest()) { |
| return; |
| } |
| |
| final Throwable[] throwables = new Throwable[1]; |
| |
| SwingUtilities.invokeAndWait(new Runnable() { |
| @Override |
| public void run() { |
| try { |
| ourTestThread = Thread.currentThread(); |
| startRunAndTear(); |
| } |
| catch (Throwable throwable) { |
| throwables[0] = throwable; |
| } |
| finally { |
| ourTestThread = null; |
| try { |
| Application application = ApplicationManager.getApplication(); |
| if (application instanceof ApplicationEx) { |
| PlatformTestCase.cleanupApplicationCaches(ourProject); |
| } |
| resetAllFields(); |
| } |
| catch (Throwable e) { |
| e.printStackTrace(); |
| } |
| } |
| } |
| }); |
| |
| if (throwables[0] != null) { |
| throw throwables[0]; |
| } |
| |
| // just to make sure all deferred Runnables to finish |
| SwingUtilities.invokeAndWait(EmptyRunnable.getInstance()); |
| |
| if (IdeaLogger.ourErrorsOccurred != null) { |
| throw IdeaLogger.ourErrorsOccurred; |
| } |
| } |
| |
| private void startRunAndTear() throws Throwable { |
| setUp(); |
| try { |
| ourAssertionsInTestDetected = true; |
| runTest(); |
| ourAssertionsInTestDetected = false; |
| } |
| finally { |
| //try{ |
| tearDown(); |
| //} |
| //catch(Throwable th){ |
| // noinspection CallToPrintStackTrace |
| //th.printStackTrace(); |
| //} |
| } |
| } |
| |
| @Override |
| public Object getData(String dataId) { |
| return ourProject == null || ourProject.isDisposed() ? null : new TestDataProvider(ourProject).getData(dataId); |
| } |
| |
| protected Sdk getProjectJDK() { |
| return null; |
| } |
| |
| protected ModuleType getModuleType() { |
| return EmptyModuleType.getInstance(); |
| } |
| |
| /** |
| * Creates dummy source file. One is not placed under source root so some PSI functions like resolve to external classes |
| * may not work. Though it works significantly faster and yet can be used if you need to create some PSI structures for |
| * test purposes |
| * |
| * @param fileName - name of the file to create. Extension is used to choose what PSI should be created like java, jsp, aj, xml etc. |
| * @param text - file text. |
| * @return dummy psi file. |
| * @throws com.intellij.util.IncorrectOperationException |
| * |
| */ |
| protected static PsiFile createFile(@NonNls String fileName, @NonNls String text) throws IncorrectOperationException { |
| FileType fileType = FileTypeManager.getInstance().getFileTypeByFileName(fileName); |
| return PsiFileFactory.getInstance(getProject()) |
| .createFileFromText(fileName, fileType, text, LocalTimeCounter.currentTime(), true, false); |
| } |
| |
| protected static PsiFile createLightFile(@NonNls String fileName, String text) throws IncorrectOperationException { |
| FileType fileType = FileTypeManager.getInstance().getFileTypeByFileName(fileName); |
| return PsiFileFactory.getInstance(getProject()) |
| .createFileFromText(fileName, fileType, text, LocalTimeCounter.currentTime(), false, false); |
| } |
| |
| /** |
| * Convenient conversion of testSomeTest -> someTest | SomeTest where testSomeTest is the name of current test. |
| * |
| * @param lowercaseFirstLetter - whether first letter after test should be lowercased. |
| */ |
| @Override |
| protected String getTestName(boolean lowercaseFirstLetter) { |
| String name = getName(); |
| assertTrue("Test name should start with 'test': " + name, name.startsWith("test")); |
| name = name.substring("test".length()); |
| if (!name.isEmpty() && lowercaseFirstLetter && !UsefulTestCase.isAllUppercaseName(name)) { |
| name = Character.toLowerCase(name.charAt(0)) + name.substring(1); |
| } |
| return name; |
| } |
| |
| protected static void commitDocument(final Document document) { |
| PsiDocumentManager.getInstance(getProject()).commitDocument(document); |
| } |
| |
| protected static void commitAllDocuments() { |
| PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); |
| } |
| |
| @Override |
| protected CodeStyleSettings getCurrentCodeStyleSettings() { |
| if (CodeStyleSchemes.getInstance().getCurrentScheme() == null) return new CodeStyleSettings(); |
| return CodeStyleSettingsManager.getSettings(getProject()); |
| } |
| |
| protected static Document getDocument(final PsiFile file) { |
| return PsiDocumentManager.getInstance(getProject()).getDocument(file); |
| } |
| |
| @SuppressWarnings("NonPrivateFieldAccessedInSynchronizedContext") |
| public static synchronized void closeAndDeleteProject() { |
| if (ourProject != null) { |
| ApplicationManager.getApplication().assertWriteAccessAllowed(); |
| |
| ((ProjectImpl)ourProject).setTemporarilyDisposed(false); |
| VirtualFile projectFile = ((ProjectEx)ourProject).getStateStore().getProjectFile(); |
| File ioFile = projectFile == null ? null : VfsUtilCore.virtualToIoFile(projectFile); |
| if (!ourProject.isDisposed()) Disposer.dispose(ourProject); |
| |
| if (ioFile != null) { |
| File dir = ioFile.getParentFile(); |
| if (dir.getName().startsWith(UsefulTestCase.TEMP_DIR_MARKER)) { |
| FileUtil.delete(dir); |
| } |
| else { |
| FileUtil.delete(ioFile); |
| } |
| } |
| |
| ProjectManagerEx.getInstanceEx().closeTestProject(ourProject); |
| ourProject = null; |
| ourPathToKeep = null; |
| } |
| } |
| |
| private static void registerShutdownHook() { |
| ShutDownTracker.getInstance().registerShutdownTask(new Runnable() { |
| @Override |
| public void run() { |
| ShutDownTracker.invokeAndWait(true, true, new Runnable() { |
| @Override |
| public void run() { |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| closeAndDeleteProject(); |
| } |
| }); |
| } |
| }); |
| } |
| }); |
| } |
| |
| private static class SimpleLightProjectDescriptor implements LightProjectDescriptor { |
| private final ModuleType myModuleType; |
| private final Sdk mySdk; |
| |
| SimpleLightProjectDescriptor(ModuleType moduleType, Sdk sdk) { |
| myModuleType = moduleType; |
| mySdk = sdk; |
| } |
| |
| @Override |
| public ModuleType getModuleType() { |
| return myModuleType; |
| } |
| |
| @Override |
| public Sdk getSdk() { |
| return mySdk; |
| } |
| |
| @Override |
| public void configureModule(Module module, ModifiableRootModel model, ContentEntry contentEntry) { |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (this == o) return true; |
| if (o == null || getClass() != o.getClass()) return false; |
| |
| SimpleLightProjectDescriptor that = (SimpleLightProjectDescriptor)o; |
| |
| if (myModuleType != null ? !myModuleType.equals(that.myModuleType) : that.myModuleType != null) return false; |
| return areJdksEqual(that.getSdk()); |
| } |
| |
| @Override |
| public int hashCode() { |
| return myModuleType != null ? myModuleType.hashCode() : 0; |
| } |
| |
| private boolean areJdksEqual(final Sdk newSdk) { |
| if (mySdk == null || newSdk == null) return mySdk == newSdk; |
| |
| final String[] myUrls = mySdk.getRootProvider().getUrls(OrderRootType.CLASSES); |
| final String[] newUrls = newSdk.getRootProvider().getUrls(OrderRootType.CLASSES); |
| return ContainerUtil.newHashSet(myUrls).equals(ContainerUtil.newHashSet(newUrls)); |
| } |
| } |
| } |