private void applyChildrenChangeEvents(VirtualFile parent, List<VFileEvent> events) {
    final NewVirtualFileSystem delegate = getDelegate(parent);
    TIntArrayList childrenIdsUpdated = new TIntArrayList();
    List<VirtualFile> childrenToBeUpdated = new SmartList<VirtualFile>();

    assert parent != null && parent != mySuperRoot;
    final int parentId = getFileId(parent);
    assert parentId != 0;
    TIntHashSet parentChildrenIds = new TIntHashSet(FSRecords.list(parentId));
    boolean hasRemovedChildren = false;

    for (VFileEvent event : events) {
      if (event instanceof VFileCreateEvent) {
        String name = ((VFileCreateEvent) event).getChildName();
        final VirtualFile fake = new FakeVirtualFile(parent, name);
        final FileAttributes attributes = delegate.getAttributes(fake);

        if (attributes != null) {
          final int childId = createAndFillRecord(delegate, fake, parentId, attributes);
          assert parent instanceof VirtualDirectoryImpl : parent;
          final VirtualDirectoryImpl dir = (VirtualDirectoryImpl) parent;
          VirtualFileSystemEntry child = dir.createChild(name, childId, dir.getFileSystem());
          childrenToBeUpdated.add(child);
          childrenIdsUpdated.add(childId);
          parentChildrenIds.add(childId);
        }
      } else if (event instanceof VFileDeleteEvent) {
        VirtualFile file = ((VFileDeleteEvent) event).getFile();
        if (!file.exists()) {
          LOG.error("Deleting a file, which does not exist: " + file.getPath());
          continue;
        }

        hasRemovedChildren = true;
        int id = getFileId(file);

        childrenToBeUpdated.add(file);
        childrenIdsUpdated.add(-id);
        parentChildrenIds.remove(id);
      }
    }

    FSRecords.updateList(parentId, parentChildrenIds.toArray());

    if (hasRemovedChildren) clearIdCache();
    VirtualDirectoryImpl parentImpl = (VirtualDirectoryImpl) parent;

    for (int i = 0, len = childrenIdsUpdated.size(); i < len; ++i) {
      final int childId = childrenIdsUpdated.get(i);
      final VirtualFile childFile = childrenToBeUpdated.get(i);

      if (childId > 0) {
        parentImpl.addChild((VirtualFileSystemEntry) childFile);
      } else {
        FSRecords.deleteRecordRecursively(-childId);
        parentImpl.removeChild(childFile);
        invalidateSubtree(childFile);
      }
    }
  }
  public void testList() {
    // Long-long
    TLongArrayList llist = new TLongArrayList();
    assertTrue(serializesCorrectly(llist, "list-l-1"));
    llist.add(0);
    llist.add(1);
    assertTrue(serializesCorrectly(llist, "list-l-2"));
    llist.add(Long.MIN_VALUE);
    assertTrue(serializesCorrectly(llist, "list-l-3"));
    llist.add(Long.MAX_VALUE);
    assertTrue(serializesCorrectly(llist, "list-l-4"));

    // Int-int
    TIntArrayList ilist = new TIntArrayList();
    assertTrue(serializesCorrectly(ilist, "list-i-1"));
    ilist.add(0);
    ilist.add(1);
    assertTrue(serializesCorrectly(ilist, "list-i-2"));
    ilist.add(Integer.MIN_VALUE);
    assertTrue(serializesCorrectly(ilist, "list-i-3"));
    ilist.add(Integer.MAX_VALUE);
    assertTrue(serializesCorrectly(ilist, "list-i-4"));

    // Double-double
    TDoubleArrayList dlist = new TDoubleArrayList();
    assertTrue(serializesCorrectly(dlist, "list-d-1"));
    dlist.add(0);
    dlist.add(1);
    assertTrue(serializesCorrectly(dlist, "list-d-2"));
    dlist.add(Double.MIN_VALUE);
    assertTrue(serializesCorrectly(dlist, "list-d-3"));
    dlist.add(Double.MAX_VALUE);
    assertTrue(serializesCorrectly(dlist, "list-d-4"));
    // NOTE: trove doesn't deal well with NaN
    //        ddmap.add( Double.NaN, Double.NaN );
    //        assertTrue( serializesCorrectly( ddmap ) );
    dlist.add(Double.POSITIVE_INFINITY);
    assertTrue(serializesCorrectly(dlist, "list-d-5"));
    dlist.add(Double.NEGATIVE_INFINITY);
    assertTrue(serializesCorrectly(dlist, "list-d-6"));

    // Float-float
    TFloatArrayList flist = new TFloatArrayList();
    assertTrue(serializesCorrectly(flist, "list-f-1"));
    flist.add(0);
    flist.add(1);
    assertTrue(serializesCorrectly(flist, "list-f-2"));
    flist.add(Float.MIN_VALUE);
    assertTrue(serializesCorrectly(flist, "list-f-3"));
    flist.add(Float.MAX_VALUE);
    assertTrue(serializesCorrectly(flist, "list-f-4"));
    flist.add(Float.POSITIVE_INFINITY);
    assertTrue(serializesCorrectly(flist, "list-f-5"));
    flist.add(Float.NEGATIVE_INFINITY);
    assertTrue(serializesCorrectly(flist, "list-f-6"));
    // NOTE: trove doesn't deal well with NaN
    //        ffmap.add( Float.NaN );
    //        assertTrue( serializesCorrectly( ffmap ) );
  }
Пример #3
0
  @Nullable
  private VirtualFileSystemEntry findFileById(
      int id, boolean cachedOnly, TIntArrayList visited, int mask) {
    VirtualFileSystemEntry cached = myIdToDirCache.get(id);
    if (cached != null) return cached;

    if (visited != null
        && (visited.size() >= DEPTH_LIMIT || (mask & id) == id && visited.contains(id))) {
      @NonNls
      String sb =
          "Dead loop detected in persistent FS (id=" + id + " cached-only=" + cachedOnly + "):";
      for (int i = 0; i < visited.size(); i++) {
        int _id = visited.get(i);
        sb +=
            "\n  "
                + _id
                + " '"
                + getName(_id)
                + "' "
                + String.format("%02x", getFileAttributes(_id))
                + ' '
                + myIdToDirCache.containsKey(_id);
      }
      LOG.error(sb);
      return null;
    }

    int parentId = getParent(id);
    if (parentId >= id) {
      if (visited == null) visited = new TIntArrayList(DEPTH_LIMIT);
    }
    if (visited != null) visited.add(id);

    VirtualFileSystemEntry result;
    if (parentId == 0) {
      myRootsLock.readLock().lock();
      try {
        result = myRootsById.get(id);
      } finally {
        myRootsLock.readLock().unlock();
      }
    } else {
      VirtualFileSystemEntry parentFile = findFileById(parentId, cachedOnly, visited, mask | id);
      if (parentFile instanceof VirtualDirectoryImpl) {
        result = ((VirtualDirectoryImpl) parentFile).findChildById(id, cachedOnly);
      } else {
        result = null;
      }
    }

    if (result != null && result.isDirectory()) {
      VirtualFileSystemEntry old = myIdToDirCache.put(id, result);
      if (old != null) result = old;
    }
    return result;
  }
Пример #4
0
  private List index(int numEvents, EventStream es, TObjectIntHashMap predicateIndex) {
    TObjectIntHashMap omap = new TObjectIntHashMap();
    int outcomeCount = 0;
    List eventsToCompare = new ArrayList(numEvents);
    TIntArrayList indexedContext = new TIntArrayList();
    while (es.hasNext()) {
      Event ev = es.nextEvent();
      String[] econtext = ev.getContext();
      ComparableEvent ce;

      int ocID;
      String oc = ev.getOutcome();

      if (omap.containsKey(oc)) {
        ocID = omap.get(oc);
      } else {
        ocID = outcomeCount++;
        omap.put(oc, ocID);
      }

      for (int i = 0; i < econtext.length; i++) {
        String pred = econtext[i];
        if (predicateIndex.containsKey(pred)) {
          indexedContext.add(predicateIndex.get(pred));
        }
      }

      // drop events with no active features
      if (indexedContext.size() > 0) {
        ce = new ComparableEvent(ocID, indexedContext.toNativeArray());
        eventsToCompare.add(ce);
      } else {
        System.err.println(
            "Dropped event " + ev.getOutcome() + ":" + Arrays.asList(ev.getContext()));
      }
      // recycle the TIntArrayList
      indexedContext.resetQuick();
    }
    outcomeLabels = toIndexedStringArray(omap);
    predLabels = toIndexedStringArray(predicateIndex);
    return eventsToCompare;
  }
 private void queueUnresolvedFilesSinceLastRestart() {
   PersistentFS fs = PersistentFS.getInstance();
   int maxId = FSRecords.getMaxId();
   TIntArrayList list = new TIntArrayList();
   for (int id = fileIsResolved.nextClearBit(1);
       id >= 0 && id < maxId;
       id = fileIsResolved.nextClearBit(id + 1)) {
     int nextSetBit = fileIsResolved.nextSetBit(id);
     int endOfRun = Math.min(maxId, nextSetBit == -1 ? maxId : nextSetBit);
     do {
       VirtualFile virtualFile = fs.findFileById(id);
       if (queueIfNeeded(virtualFile, myProject)) {
         list.add(id);
       } else {
         fileIsResolved.set(id);
       }
     } while (++id < endOfRun);
   }
   log("Initially added to resolve " + toVfString(list.toNativeArray()));
 }
  private void storeIds(@NotNull ConcurrentIntObjectMap<int[]> fileToForwardIds) {
    int forwardSize = 0;
    int backwardSize = 0;
    final TIntObjectHashMap<TIntArrayList> fileToBackwardIds =
        new TIntObjectHashMap<TIntArrayList>(fileToForwardIds.size());
    for (ConcurrentIntObjectMap.IntEntry<int[]> entry : fileToForwardIds.entries()) {
      int fileId = entry.getKey();
      int[] forwardIds = entry.getValue();
      forwardSize += forwardIds.length;
      for (int forwardId : forwardIds) {
        TIntArrayList backIds = fileToBackwardIds.get(forwardId);
        if (backIds == null) {
          backIds = new TIntArrayList();
          fileToBackwardIds.put(forwardId, backIds);
        }
        backIds.add(fileId);
        backwardSize++;
      }
    }
    log("backwardSize = " + backwardSize);
    log("forwardSize = " + forwardSize);
    log("fileToForwardIds.size() = " + fileToForwardIds.size());
    log("fileToBackwardIds.size() = " + fileToBackwardIds.size());
    assert forwardSize == backwardSize;

    // wrap in read action so that sudden quit (in write action) would not interrupt us
    myApplication.runReadAction(
        () -> {
          if (!myApplication.isDisposed()) {
            fileToBackwardIds.forEachEntry(
                new TIntObjectProcedure<TIntArrayList>() {
                  @Override
                  public boolean execute(int fileId, TIntArrayList backIds) {
                    storage.addAll(fileId, backIds.toNativeArray());
                    return true;
                  }
                });
          }
        });
  }
  @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()]);
  }
  @Override
  @NotNull
  public List<TextEditorHighlightingPass> instantiatePasses(
      @NotNull final PsiFile psiFile,
      @NotNull final Editor editor,
      @NotNull final int[] passesToIgnore) {
    synchronized (this) {
      if (!checkedForCycles) {
        checkedForCycles = true;
        checkForCycles();
      }
    }
    PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject);
    final Document document = editor.getDocument();
    PsiFile fileFromDoc = documentManager.getPsiFile(document);
    if (!(fileFromDoc instanceof PsiCompiledElement)) {
      assert fileFromDoc == psiFile : "Files are different: " + psiFile + ";" + fileFromDoc;
      Document documentFromFile = documentManager.getDocument(psiFile);
      assert documentFromFile == document
          : "Documents are different. Doc: "
              + document
              + "; Doc from file: "
              + documentFromFile
              + "; File: "
              + psiFile
              + "; Virtual file: "
              + PsiUtilCore.getVirtualFile(psiFile);
    }
    final TIntObjectHashMap<TextEditorHighlightingPass> id2Pass =
        new TIntObjectHashMap<TextEditorHighlightingPass>();
    final TIntArrayList passesRefusedToCreate = new TIntArrayList();
    myRegisteredPassFactories.forEachKey(
        new TIntProcedure() {
          @Override
          public boolean execute(int passId) {
            if (ArrayUtil.find(passesToIgnore, passId) != -1) {
              return true;
            }
            PassConfig passConfig = myRegisteredPassFactories.get(passId);
            TextEditorHighlightingPassFactory factory = passConfig.passFactory;
            final TextEditorHighlightingPass pass = factory.createHighlightingPass(psiFile, editor);

            if (pass == null) {
              passesRefusedToCreate.add(passId);
            } else {
              // init with editor's colors scheme
              pass.setColorsScheme(editor.getColorsScheme());

              TIntArrayList ids = new TIntArrayList(passConfig.completionPredecessorIds.length);
              for (int id : passConfig.completionPredecessorIds) {
                if (myRegisteredPassFactories.containsKey(id)) ids.add(id);
              }
              pass.setCompletionPredecessorIds(
                  ids.isEmpty() ? ArrayUtil.EMPTY_INT_ARRAY : ids.toNativeArray());
              ids = new TIntArrayList(passConfig.startingPredecessorIds.length);
              for (int id : passConfig.startingPredecessorIds) {
                if (myRegisteredPassFactories.containsKey(id)) ids.add(id);
              }
              pass.setStartingPredecessorIds(
                  ids.isEmpty() ? ArrayUtil.EMPTY_INT_ARRAY : ids.toNativeArray());
              pass.setId(passId);
              id2Pass.put(passId, pass);
            }
            return true;
          }
        });

    DaemonCodeAnalyzerEx daemonCodeAnalyzer = DaemonCodeAnalyzerEx.getInstanceEx(myProject);
    final FileStatusMap statusMap = daemonCodeAnalyzer.getFileStatusMap();
    passesRefusedToCreate.forEach(
        new TIntProcedure() {
          @Override
          public boolean execute(int passId) {
            statusMap.markFileUpToDate(document, passId);
            return true;
          }
        });

    return (List) Arrays.asList(id2Pass.getValues());
  }