@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);
 }
Example #20
0
  @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()]);
  }