@Override public void saveAllDocuments() { ApplicationManager.getApplication().assertIsDispatchThread(); myMultiCaster.beforeAllDocumentsSaving(); if (myUnsavedDocuments.isEmpty()) return; final Map<Document, IOException> failedToSave = new HashMap<Document, IOException>(); final Set<Document> vetoed = new HashSet<Document>(); while (true) { int count = 0; for (Document document : myUnsavedDocuments) { if (failedToSave.containsKey(document)) continue; if (vetoed.contains(document)) continue; try { doSaveDocument(document); } catch (IOException e) { //noinspection ThrowableResultOfMethodCallIgnored failedToSave.put(document, e); } catch (SaveVetoException e) { vetoed.add(document); } count++; } if (count == 0) break; } if (!failedToSave.isEmpty()) { handleErrorsOnSave(failedToSave); } }
@Override @NotNull public Project[] getOpenProjects() { synchronized (myOpenProjects) { if (myOpenProjectsArrayCache.length != myOpenProjects.size()) { LOG.error( "Open projects: " + myOpenProjects + "; cache: " + Arrays.asList(myOpenProjectsArrayCache)); } if (myOpenProjectsArrayCache.length > 0 && myOpenProjectsArrayCache[0] != myOpenProjects.get(0)) { LOG.error( "Open projects cache corrupted. Open projects: " + myOpenProjects + "; cache: " + Arrays.asList(myOpenProjectsArrayCache)); } if (ApplicationManager.getApplication().isUnitTestMode()) { Project[] testProjects = myTestProjects.toArray(new Project[myTestProjects.size()]); for (Project testProject : testProjects) { assert !testProject.isDisposed() : testProject; } return ArrayUtil.mergeArrays(myOpenProjectsArrayCache, testProjects); } return myOpenProjectsArrayCache; } }
private synchronized void assertAllPointersDisposed() { for (Map.Entry<VirtualFilePointerListener, FilePointerPartNode> entry : myPointers.entrySet()) { FilePointerPartNode root = entry.getValue(); ArrayList<FilePointerPartNode> left = new ArrayList<FilePointerPartNode>(); root.getPointersUnder(null, false, "", left); if (!left.isEmpty()) { VirtualFilePointerImpl p = left.get(0).leaf; try { p.throwDisposalError("Not disposed pointer: " + p); } finally { for (FilePointerPartNode pair : left) { VirtualFilePointerImpl pointer = pair.leaf; pointer.dispose(); } } } } synchronized (myContainers) { if (!myContainers.isEmpty()) { VirtualFilePointerContainerImpl container = myContainers.iterator().next(); container.throwDisposalError("Not disposed container"); } } }
@NotNull private static GlobalSearchScope forDirectory( @NotNull Project project, boolean withSubdirectories, @NotNull VirtualFile directory) { Set<VirtualFile> result = new LinkedHashSet<>(); result.add(directory); addSourceDirectoriesFromLibraries(project, directory, result); VirtualFile[] array = result.toArray(new VirtualFile[result.size()]); return GlobalSearchScopesCore.directoriesScope(project, withSubdirectories, array); }
public CmdlineRemoteProto.Message.ControllerMessage.FSEvent createNextEvent() { final CmdlineRemoteProto.Message.ControllerMessage.FSEvent.Builder builder = CmdlineRemoteProto.Message.ControllerMessage.FSEvent.newBuilder(); builder.setOrdinal(++myNextEventOrdinal); builder.addAllChangedPaths(myChanged); myChanged.clear(); builder.addAllDeletedPaths(myDeleted); myDeleted.clear(); return builder.build(); }
private static void processLibrariesAndJpsPlugins( final File jarFile, final File zipFile, final String pluginName, final Set<Library> libs, Map<Module, String> jpsModules, final ProgressIndicator progressIndicator) throws IOException { if (FileUtil.ensureCanCreateFile(zipFile)) { ZipOutputStream zos = null; try { zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile))); addStructure(pluginName, zos); addStructure(pluginName + "/" + MIDDLE_LIB_DIR, zos); final String entryName = pluginName + JAR_EXTENSION; ZipUtil.addFileToZip( zos, jarFile, getZipPath(pluginName, entryName), new HashSet<String>(), createFilter(progressIndicator, FileTypeManager.getInstance())); for (Map.Entry<Module, String> entry : jpsModules.entrySet()) { File jpsPluginJar = jarModulesOutput(Collections.singleton(entry.getKey()), null, null); ZipUtil.addFileToZip( zos, jpsPluginJar, getZipPath(pluginName, entry.getValue()), null, null); } Set<String> usedJarNames = new HashSet<String>(); usedJarNames.add(entryName); Set<VirtualFile> jarredVirtualFiles = new HashSet<VirtualFile>(); for (Library library : libs) { final VirtualFile[] files = library.getFiles(OrderRootType.CLASSES); for (VirtualFile virtualFile : files) { if (jarredVirtualFiles.add(virtualFile)) { if (virtualFile.getFileSystem() instanceof JarFileSystem) { addLibraryJar( virtualFile, zipFile, pluginName, zos, usedJarNames, progressIndicator); } else { makeAndAddLibraryJar( virtualFile, zipFile, pluginName, zos, usedJarNames, progressIndicator, library.getName()); } } } } } finally { if (zos != null) zos.close(); } } }
@TestOnly public void dropAllUnsavedDocuments() { if (!ApplicationManager.getApplication().isUnitTestMode()) { throw new RuntimeException("This method is only for test mode!"); } ApplicationManager.getApplication().assertWriteAccessAllowed(); if (!myUnsavedDocuments.isEmpty()) { myUnsavedDocuments.clear(); fireUnsavedDocumentsDropped(); } }
@Override public void run() { while (!myDisposed) { boolean isEmpty; synchronized (filesToResolve) { isEmpty = filesToResolve.isEmpty(); } if (enableVetoes.get() > 0 || isEmpty || !resolveProcess.isDone() || HeavyProcessLatch.INSTANCE.isRunning() || PsiDocumentManager.getInstance(myProject).hasUncommitedDocuments()) { try { waitForQueue(); } catch (InterruptedException e) { break; } continue; } final Set<VirtualFile> files = pollFilesToResolve(); if (files.isEmpty()) continue; upToDate = false; myApplication.invokeLater( () -> { if (!resolveProcess.isDone()) return; log("Started to resolve " + files.size() + " files"); Task.Backgroundable backgroundable = new Task.Backgroundable(myProject, "Resolving files...", false) { @Override public void run(@NotNull final ProgressIndicator indicator) { if (!myApplication.isDisposed()) { processBatch(indicator, files); } } }; ProgressIndicator indicator; if (files.size() > 1) { // show progress indicator = new BackgroundableProcessIndicator(backgroundable); } else { indicator = new MyProgress(); } resolveProcess = ((ProgressManagerImpl) ProgressManager.getInstance()) .runProcessWithProgressAsynchronously(backgroundable, indicator, null); }, myProject.getDisposed()); flushLog(); } }
// return true if continue to process sub-directories of the {@code file}, false if the file is // already processed private boolean doCountAndMarkUnresolved( @NotNull VirtualFile file, @NotNull Set<VirtualFile> result) { if (file.isDirectory()) { fileIsResolved.set(getAbsId(file)); return result.add(file); } if (toResolve(file, myProject)) { result.add(file); fileIsResolved.clear(getAbsId(file)); } return true; }
@Override public boolean canCloseProject(Project project) { if (!myUnsavedDocuments.isEmpty()) { myOnClose = true; try { saveAllDocuments(); } finally { myOnClose = false; } } return myUnsavedDocuments.isEmpty(); }
@TestOnly public void assertPointersAreDisposed() { List<VirtualFilePointerImpl> pointers = new ArrayList<VirtualFilePointerImpl>(); addAllPointers(pointers); try { for (VirtualFilePointerImpl pointer : pointers) { if (!myStoredPointers.contains(pointer)) { pointer.throwDisposalError("Virtual pointer hasn't been disposed: " + pointer); } } } finally { myStoredPointers.clear(); } }
@NotNull private Set<VirtualFile> pollFilesToResolve() { Set<VirtualFile> set; synchronized (filesToResolve) { int queuedSize = filesToResolve.size(); set = new LinkedHashSet<VirtualFile>(queuedSize); // someone might have cleared this bit to mark file as processed for (VirtualFile file : filesToResolve) { if (fileIsInQueue.clear(getAbsId(file))) { set.add(file); } } filesToResolve.clear(); } return countAndMarkUnresolved(set, false); }
private void doSaveDocument(@NotNull final Document document) throws IOException, SaveVetoException { VirtualFile file = getFile(document); if (file == null || file instanceof LightVirtualFile || file.isValid() && !isFileModified(file)) { removeFromUnsaved(document); return; } if (file.isValid() && needsRefresh(file)) { file.refresh(false, false); if (!myUnsavedDocuments.contains(document)) return; } for (FileDocumentSynchronizationVetoer vetoer : Extensions.getExtensions(FileDocumentSynchronizationVetoer.EP_NAME)) { if (!vetoer.maySaveDocument(document)) { throw new SaveVetoException(); } } final AccessToken token = ApplicationManager.getApplication().acquireWriteActionLock(getClass()); try { doSaveDocumentInWriteAction(document, file); } finally { token.finish(); } }
private VirtualFilePointerContainer registerContainer( @NotNull Disposable parent, @NotNull final VirtualFilePointerContainerImpl virtualFilePointerContainer) { synchronized (myContainers) { myContainers.add(virtualFilePointerContainer); } Disposer.register( parent, new Disposable() { @Override public void dispose() { Disposer.dispose(virtualFilePointerContainer); boolean removed; synchronized (myContainers) { removed = myContainers.remove(virtualFilePointerContainer); } if (!ApplicationManager.getApplication().isUnitTestMode()) { assert removed; } } public String toString() { return "Disposing container " + virtualFilePointerContainer; } }); return virtualFilePointerContainer; }
@Override public Collection<Project> closeTestProject(@NotNull Project project) { synchronized (myOpenProjects) { assert ApplicationManager.getApplication().isUnitTestMode(); myTestProjects.remove(project); return myTestProjects; } }
@Override public void openTestProject(@NotNull final Project project) { synchronized (myOpenProjects) { assert ApplicationManager.getApplication().isUnitTestMode(); assert !project.isDisposed() : "Must not open already disposed project"; myTestProjects.add(project); } }
@Override public boolean isProjectOpened(Project project) { synchronized (myOpenProjects) { return ApplicationManager.getApplication().isUnitTestMode() && myTestProjects.contains(project) || myOpenProjects.contains(project); } }
private void resolveReference( @NotNull PsiReference reference, @NotNull Set<PsiElement> resolved) { PsiElement element = reference.resolve(); if (element != null) { resolved.add(element); } refCount.incrementAndGet(); }
private void updateDocumentFromPropertyValue( final String value, final Document document, final PropertiesFile propertiesFile) { @NonNls String text = value; if (myBackSlashPressed.contains(propertiesFile)) { text += "\\"; } document.replaceString(0, document.getTextLength(), text); }
@NotNull private static List<VFileEvent> validateEvents(@NotNull List<VFileEvent> events) { final List<EventWrapper> deletionEvents = ContainerUtil.newArrayList(); for (int i = 0, size = events.size(); i < size; i++) { final VFileEvent event = events.get(i); if (event instanceof VFileDeleteEvent && event.isValid()) { deletionEvents.add(new EventWrapper((VFileDeleteEvent) event, i)); } } final TIntHashSet invalidIDs; if (deletionEvents.isEmpty()) { invalidIDs = EmptyIntHashSet.INSTANCE; } else { ContainerUtil.quickSort(deletionEvents, DEPTH_COMPARATOR); invalidIDs = new TIntHashSet(deletionEvents.size()); final Set<VirtualFile> dirsToBeDeleted = new THashSet<VirtualFile>(deletionEvents.size()); nextEvent: for (EventWrapper wrapper : deletionEvents) { final VirtualFile candidate = wrapper.event.getFile(); VirtualFile parent = candidate; while (parent != null) { if (dirsToBeDeleted.contains(parent)) { invalidIDs.add(wrapper.id); continue nextEvent; } parent = parent.getParent(); } if (candidate.isDirectory()) { dirsToBeDeleted.add(candidate); } } } final List<VFileEvent> filtered = new ArrayList<VFileEvent>(events.size() - invalidIDs.size()); for (int i = 0, size = events.size(); i < size; i++) { final VFileEvent event = events.get(i); if (event.isValid() && !(event instanceof VFileDeleteEvent && invalidIDs.contains(i))) { filtered.add(event); } } return filtered; }
private static void collectModules(Module module, Set<Module> result, Module[] allModules) { if (!result.add(module)) { return; } for (Module otherModule : allModules) { if (ModuleRootManager.getInstance(otherModule).isDependsOn(module)) { collectModules(otherModule, result, allModules); } } }
@Override @NotNull public Document[] getUnsavedDocuments() { if (myUnsavedDocuments.isEmpty()) { return Document.EMPTY_ARRAY; } List<Document> list = new ArrayList<Document>(myUnsavedDocuments); return list.toArray(new Document[list.size()]); }
private void selectionChanged() { myBackSlashPressed.clear(); UIUtil.invokeLaterIfNeeded( new Runnable() { @Override public void run() { updateEditorsFromProperties(); } }); }
public synchronized void assertPointersDisposed() { for (Map.Entry<VirtualFilePointerListener, TreeMap<String, VirtualFilePointerImpl>> entry : myUrlToPointerMaps.entrySet()) { VirtualFilePointerListener listener = entry.getKey(); TreeMap<String, VirtualFilePointerImpl> map = entry.getValue(); for (VirtualFilePointerImpl pointer : map.values()) { myUrlToPointerMaps.clear(); pointer.throwNotDisposedError("Not disposed pointer: listener=" + listener); } } synchronized (myContainers) { if (!myContainers.isEmpty()) { VirtualFilePointerContainerImpl container = myContainers.iterator().next(); myContainers.clear(); throw new RuntimeException("Not disposed container " + container); } } }
private static void unexcludeRootIfNeccessary( @NotNull VirtualFile root, @NotNull ModuleRootManager manager) { Set<VirtualFile> excludedRoots = new HashSet<VirtualFile>(Arrays.asList(manager.getExcludeRoots())); VirtualFile excludedRoot = root; while (excludedRoot != null && !excludedRoots.contains(excludedRoot)) { excludedRoot = excludedRoot.getParent(); } if (excludedRoot == null) { return; } Set<VirtualFile> rootsToExclude = new HashSet<VirtualFile>(); collectChildrenRecursively(excludedRoot, root, rootsToExclude); final ModifiableRootModel model = manager.getModifiableModel(); ContentEntry contentEntry = findContentEntryForRoot(model, excludedRoot); if (contentEntry != null) { ExcludeFolder excludedFolder = null; for (ExcludeFolder folder : contentEntry.getExcludeFolders()) { if (folder.getFile() == excludedRoot) { excludedFolder = folder; break; } } if (excludedFolder != null) { contentEntry.removeExcludeFolder(excludedFolder); } for (VirtualFile rootToExclude : rootsToExclude) { if (!excludedRoots.contains(rootToExclude)) { contentEntry.addExcludeFolder(rootToExclude); } } } ApplicationManager.getApplication() .runWriteAction( new Runnable() { @Override public void run() { model.commit(); } }); }
@Override public void saveDocument(@NotNull final Document document) { ApplicationManager.getApplication().assertIsDispatchThread(); if (!myUnsavedDocuments.contains(document)) return; try { doSaveDocument(document); } catch (IOException e) { handleErrorsOnSave(Collections.singletonMap(document, e)); } catch (SaveVetoException ignored) { } }
private void addPackage(@NotNull final String packageName, @NotNull final String packagePath) { myLibRootUrls.add(VfsUtilCore.pathToUrl(packagePath)); List<String> paths = myPackagesMap.get((packageName)); if (paths == null) { paths = new SmartList<String>(); myPackagesMap.put(packageName, paths); } if (!paths.contains(packagePath)) { paths.add(packagePath); } }
private void assertEvent(Class<? extends VFileEvent> type, String... paths) { List<VFileEvent> events = getEvents(type.getSimpleName(), null); assertEquals(events.toString(), paths.length, events.size()); Set<String> pathSet = ContainerUtil.map2Set( paths, new Function<String, String>() { @Override public String fun(final String path) { return FileUtil.toSystemIndependentName(path); } }); for (VFileEvent event : events) { assertTrue(event.toString(), type.isInstance(event)); VirtualFile eventFile = event.getFile(); assertNotNull(event.toString(), eventFile); assertTrue( eventFile + " not in " + Arrays.toString(paths), pathSet.remove(eventFile.getPath())); } }
private static String getLibraryJarName( final String fileName, Set<String> usedJarNames, @Nullable final String preferredName) { String uniqueName; if (preferredName != null && !usedJarNames.contains(preferredName)) { uniqueName = preferredName; } else { uniqueName = fileName; if (usedJarNames.contains(uniqueName)) { final int dotPos = uniqueName.lastIndexOf("."); final String name = dotPos < 0 ? uniqueName : uniqueName.substring(0, dotPos); final String ext = dotPos < 0 ? "" : uniqueName.substring(dotPos); int i = 0; do { i++; uniqueName = name + i + ext; } while (usedJarNames.contains(uniqueName)); } } usedJarNames.add(uniqueName); return uniqueName; }
@NotNull private FSRecords.NameId[] persistAllChildren( @NotNull final VirtualFile file, final int id, @NotNull FSRecords.NameId[] current) { assert file != mySuperRoot; final NewVirtualFileSystem fs = replaceWithNativeFS(getDelegate(file)); String[] delegateNames = VfsUtil.filterNames(fs.list(file)); if (delegateNames.length == 0 && current.length > 0) { return current; } Set<String> toAdd = ContainerUtil.newHashSet(delegateNames); for (FSRecords.NameId nameId : current) { toAdd.remove(nameId.name); } final TIntArrayList childrenIds = new TIntArrayList(current.length + toAdd.size()); final List<FSRecords.NameId> nameIds = ContainerUtil.newArrayListWithExpectedSize(current.length + toAdd.size()); for (FSRecords.NameId nameId : current) { childrenIds.add(nameId.id); nameIds.add(nameId); } for (String newName : toAdd) { FakeVirtualFile child = new FakeVirtualFile(file, newName); FileAttributes attributes = fs.getAttributes(child); if (attributes != null) { int childId = createAndFillRecord(fs, child, id, attributes); childrenIds.add(childId); nameIds.add(new FSRecords.NameId(childId, FileNameCache.storeName(newName), newName)); } } FSRecords.updateList(id, childrenIds.toNativeArray()); setChildrenCached(id); return nameIds.toArray(new FSRecords.NameId[nameIds.size()]); }