public void testExternalFileModificationWhileProjectClosed() throws Exception { VirtualFile root = ProjectRootManager.getInstance(myProject).getContentRoots()[0]; PsiClass objectClass = myJavaFacade.findClass( CommonClassNames.JAVA_LANG_OBJECT, GlobalSearchScope.allScope(getProject())); assertNotNull(objectClass); checkUsages(objectClass, new String[] {}); FileBasedIndex.getInstance() .getContainingFiles( TodoIndex.NAME, new TodoIndexEntry("todo", true), GlobalSearchScope.allScope(getProject())); final String projectLocation = myProject.getPresentableUrl(); assert projectLocation != null : myProject; PlatformTestUtil.saveProject(myProject); final VirtualFile content = ModuleRootManager.getInstance(getModule()).getContentRoots()[0]; Project project = myProject; ProjectUtil.closeAndDispose(project); InjectedLanguageManagerImpl.checkInjectorsAreDisposed(project); assertTrue("Project was not disposed", myProject.isDisposed()); myModule = null; final File file = new File(root.getPath(), "1.java"); assertTrue(file.exists()); FileUtil.writeToFile(file, "class A{ Object o;}".getBytes(CharsetToolkit.UTF8_CHARSET)); root.refresh(false, true); LocalFileSystem.getInstance().refresh(false); myProject = ProjectManager.getInstance().loadAndOpenProject(projectLocation); InjectedLanguageManagerImpl.pushInjectors(getProject()); setUpModule(); setUpJdk(); ProjectManagerEx.getInstanceEx().openTestProject(myProject); UIUtil.dispatchAllInvocationEvents(); // startup activities runStartupActivities(); PsiTestUtil.addSourceContentToRoots(getModule(), content); assertNotNull(myProject); myPsiManager = (PsiManagerImpl) PsiManager.getInstance(myProject); myJavaFacade = JavaPsiFacadeEx.getInstanceEx(myProject); objectClass = myJavaFacade.findClass( CommonClassNames.JAVA_LANG_OBJECT, GlobalSearchScope.allScope(getProject())); assertNotNull(objectClass); checkUsages(objectClass, new String[] {"1.java"}); }
@TestOnly public static void pushInjectors(@NotNull Project project) { InjectedLanguageManagerImpl cachedManager = (InjectedLanguageManagerImpl) project.getUserData(INSTANCE_CACHE); if (cachedManager == null) return; try { assert cachedManager.myInjectorsClone.isEmpty() : cachedManager.myInjectorsClone; } finally { cachedManager.myInjectorsClone.clear(); } cachedManager.myInjectorsClone.putAll(cachedManager.getInjectorMap().getBackingMap()); }
@Override protected void setUp() throws Exception { super.setUp(); myFilesToDelete.add(new File(FileUtilRt.getTempDirectory())); if (ourTestCase != null) { String message = "Previous test " + ourTestCase + " hasn't called tearDown(). Probably overridden without super call."; ourTestCase = null; fail(message); } IdeaLogger.ourErrorsOccurred = null; LOG.info(getClass().getName() + ".setUp()"); initApplication(); myEditorListenerTracker = new EditorListenerTracker(); myThreadTracker = new ThreadTracker(); setUpProject(); storeSettings(); ourTestCase = this; if (myProject != null) { ProjectManagerEx.getInstanceEx().openTestProject(myProject); CodeStyleSettingsManager.getInstance(myProject).setTemporarySettings(new CodeStyleSettings()); InjectedLanguageManagerImpl.pushInjectors(getProject()); } DocumentCommitThread.getInstance().clearQueue(); UIUtil.dispatchAllInvocationEvents(); }
@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(); InjectedLanguageManagerImpl.checkInjectorsAreDisposed(project); }
@NotNull private Set<PsiFile> getInjectedPsiFiles( @NotNull final List<PsiElement> elements1, @NotNull final List<PsiElement> elements2, @NotNull final ProgressIndicator progress) { ApplicationManager.getApplication().assertReadAccessAllowed(); final Set<PsiFile> outInjected = new THashSet<PsiFile>(); List<DocumentWindow> injected = InjectedLanguageUtil.getCachedInjectedDocuments(myFile); final Collection<PsiElement> hosts = new THashSet<PsiElement>(elements1.size() + elements2.size() + injected.size()); // rehighlight all injected PSI regardless the range, // since change in one place can lead to invalidation of injected PSI in (completely) other // place. for (DocumentWindow documentRange : injected) { progress.checkCanceled(); if (!documentRange.isValid()) continue; PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(documentRange); if (file == null) continue; PsiElement context = InjectedLanguageManager.getInstance(file.getProject()).getInjectionHost(file); if (context != null && context.isValid() && !file.getProject().isDisposed() && (myUpdateAll || myRestrictRange.intersects(context.getTextRange()))) { hosts.add(context); } } InjectedLanguageManagerImpl injectedLanguageManager = InjectedLanguageManagerImpl.getInstanceImpl(myProject); Processor<PsiElement> collectInjectableProcessor = new CommonProcessors.CollectProcessor<PsiElement>(hosts); injectedLanguageManager.processInjectableElements(elements1, collectInjectableProcessor); injectedLanguageManager.processInjectableElements(elements2, collectInjectableProcessor); final PsiLanguageInjectionHost.InjectedPsiVisitor visitor = new PsiLanguageInjectionHost.InjectedPsiVisitor() { @Override public void visit( @NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) { synchronized (outInjected) { outInjected.add(injectedPsi); } } }; if (!JobLauncher.getInstance() .invokeConcurrentlyUnderProgress( new ArrayList<PsiElement>(hosts), progress, true, new Processor<PsiElement>() { @Override public boolean process(PsiElement element) { ApplicationManager.getApplication().assertReadAccessAllowed(); progress.checkCanceled(); InjectedLanguageUtil.enumerate(element, myFile, false, visitor); return true; } })) { throw new ProcessCanceledException(); } synchronized (outInjected) { return outInjected; } }
@Override protected void tearDown() throws Exception { List<Throwable> exceptions = new SmartList<Throwable>(); Project project = myProject; if (project != null) { try { LightPlatformTestCase.doTearDown(project, ourApplication, false, exceptions); } catch (Throwable e) { exceptions.add(e); } disposeProject(exceptions); } try { checkForSettingsDamage(exceptions); } catch (Throwable e) { exceptions.add(e); } try { if (project != null) { try { InjectedLanguageManagerImpl.checkInjectorsAreDisposed(project); } catch (AssertionError e) { exceptions.add(e); } } try { for (final File fileToDelete : myFilesToDelete) { delete(fileToDelete); } LocalFileSystem.getInstance().refreshIoFiles(myFilesToDelete); } catch (Throwable e) { exceptions.add(e); } if (!myAssertionsInTestDetected) { if (IdeaLogger.ourErrorsOccurred != null) { exceptions.add(IdeaLogger.ourErrorsOccurred); } } try { super.tearDown(); } catch (Throwable e) { exceptions.add(e); } try { if (myEditorListenerTracker != null) { myEditorListenerTracker.checkListenersLeak(); } } catch (AssertionError error) { exceptions.add(error); } try { if (myThreadTracker != null) { myThreadTracker.checkLeak(); } } catch (AssertionError error) { exceptions.add(error); } try { LightPlatformTestCase.checkEditorsReleased(exceptions); } catch (Throwable error) { exceptions.add(error); } } finally { myProjectManager = null; myProject = null; myModule = null; myFilesToDelete.clear(); myEditorListenerTracker = null; myThreadTracker = null; ourTestCase = null; } CompoundRuntimeException.throwIfNotEmpty(exceptions); }
private static MultiHostRegistrarImpl probeElementsUp( @NotNull PsiElement element, @NotNull PsiFile hostPsiFile, boolean probeUp) { PsiManager psiManager = hostPsiFile.getManager(); final Project project = psiManager.getProject(); InjectedLanguageManagerImpl injectedManager = InjectedLanguageManagerImpl.getInstanceImpl(project); if (injectedManager == null) { return null; // for tests } MultiHostRegistrarImpl registrar = null; PsiElement current = element; nextParent: while (current != null && current != hostPsiFile) { ProgressManager.checkCanceled(); if ("EL".equals(current.getLanguage().getID())) break; ParameterizedCachedValue<MultiHostRegistrarImpl, PsiElement> data = current.getUserData(INJECTED_PSI); if (data == null) { registrar = InjectedPsiCachedValueProvider.doCompute( current, injectedManager, project, hostPsiFile); } else { registrar = data.getValue(current); } current = current.getParent(); // cache no injection for current if (registrar != null) { List<Pair<Place, PsiFile>> places = registrar.getResult(); // check that injections found intersect with queried element TextRange elementRange = element.getTextRange(); for (Pair<Place, PsiFile> pair : places) { Place place = pair.first; for (PsiLanguageInjectionHost.Shred shred : place) { if (shred.getHost().getTextRange().intersects(elementRange)) { if (place.isValid()) break nextParent; } } } } if (!probeUp) { break; } } if (probeUp) { // cache only if we walked all parents for (PsiElement e = element; e != current && e != null && e != hostPsiFile; e = e.getParent()) { ProgressManager.checkCanceled(); if (registrar == null) { e.putUserData(INJECTED_PSI, null); } else { ParameterizedCachedValue<MultiHostRegistrarImpl, PsiElement> cachedValue = CachedValuesManager.getManager(project) .createParameterizedCachedValue(INJECTED_PSI_PROVIDER, false); CachedValueProvider.Result<MultiHostRegistrarImpl> result = CachedValueProvider.Result.create( registrar, PsiModificationTracker.MODIFICATION_COUNT, registrar); ((PsiParameterizedCachedValue<MultiHostRegistrarImpl, PsiElement>) cachedValue) .setValue(result); e.putUserData(INJECTED_PSI, cachedValue); } } } return registrar; }