diff --git a/platform/core-impl/src/com/intellij/psi/impl/file/PsiDirectoryImpl.java b/platform/core-impl/src/com/intellij/psi/impl/file/PsiDirectoryImpl.java
index 4a8e7f0a0e07..c64a109153a7 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/file/PsiDirectoryImpl.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/file/PsiDirectoryImpl.java
@@ -215,11 +215,12 @@ public class PsiDirectoryImpl extends PsiElementBase implements PsiDirectory, Qu
ProgressIndicatorProvider.checkCanceled();
for (VirtualFile vFile : myFile.getChildren()) {
+ boolean isDir = vFile.isDirectory();
if (processor instanceof PsiFileSystemItemProcessor &&
- !((PsiFileSystemItemProcessor)processor).acceptItem(vFile.getName(), vFile.isDirectory())) {
+ !((PsiFileSystemItemProcessor)processor).acceptItem(vFile.getName(), isDir)) {
continue;
}
- if (vFile.isDirectory()) {
+ if (isDir) {
PsiDirectory dir = myManager.findDirectory(vFile);
if (dir != null) {
if (!processor.execute(dir)) return false;
diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/NewVirtualFileSystem.java b/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/NewVirtualFileSystem.java
index d0ebd6f159fb..f2ba97153912 100644
--- a/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/NewVirtualFileSystem.java
+++ b/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/NewVirtualFileSystem.java
@@ -23,6 +23,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileListener;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.VirtualFileSystem;
+import org.intellij.lang.annotations.MagicConstant;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -103,4 +104,48 @@ public abstract class NewVirtualFileSystem extends VirtualFileSystem implements
public String getCanonicallyCasedName(@NotNull VirtualFile file) {
return file.getName();
}
+
+ public static final int BA_EXISTS = 0x01;
+ public static final int BA_REGULAR = 0x02;
+ public static final int BA_DIRECTORY = 0x04;
+ public static final int BA_HIDDEN = 0x08;
+
+ @MagicConstant(flags = {BA_EXISTS, BA_REGULAR, BA_DIRECTORY, BA_HIDDEN})
+ public @interface FileBooleanAttributes {}
+
+ /**
+ * Queries the file about several attributes at once, and returns them ORed together.
+ * This method is typically faster than several methods calls querying corresponding file attributes one by one.
+ *
+ * @param file to query.
+ * @param flags Attributes to query the file for.
+ * Each attribute is an int constant from this class.
+ * Following attributes are defined:
+ *
+ * - {@link #BA_EXISTS} is set if {@link java.io.File#exists()} returns true
+ * - {@link #BA_DIRECTORY} is set if {@link java.io.File#isDirectory()} returns true
+ * - {@link #BA_HIDDEN} is set if {@link java.io.File#isHidden()} returns true
+ * - {@link #BA_REGULAR} is set if {@link java.io.File#isFile()} returns true
+ *
+ * Attributes can be bitwise ORed together to query several file attributes at once.
+ * -1 as an argument value will query all attributes.
+ * @return Attributes mask for the file, where the bit is set if the corresponding attribute for the file is true.
+ * That is, the return value is {@code
+ * (file.exists() ? BA_EXISTS : 0) |
+ * (file.isDirectory()() ? BA_DIRECTORY : 0) |
+ * (file.isRegular()() ? BA_REGULAR : 0) |
+ * (file.isHidden()() ? BA_HIDDEN : 0)
+ * }
+ * Except that the bit in the return value is undefined if the corresponding bit in the flags parameter is not set.
+ *
+ * Example usage:
+ *
{@code
+ * int attributes = getBooleanAttributes(file, BA_EXISTS | BA_DIRECTORY);
+ * if ((attributes & BA_EXISTS) != 0) {
+ * // file exists
+ * boolean isDirectory = (attributes & BA_DIRECTORY) != 0;
+ * }}
+ */
+ @FileBooleanAttributes
+ public abstract int getBooleanAttributes(@NotNull final VirtualFile file, @FileBooleanAttributes int flags);
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/ex/temp/TempFileSystem.java b/platform/platform-impl/src/com/intellij/openapi/vfs/ex/temp/TempFileSystem.java
index b2688f67df36..7f35b77eba8c 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/ex/temp/TempFileSystem.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/ex/temp/TempFileSystem.java
@@ -270,7 +270,7 @@ public class TempFileSystem extends NewVirtualFileSystem {
}
}
- private static abstract class FSItem {
+ private abstract static class FSItem {
private final FSDir myParent;
private String myName;
private long myTimestamp;
@@ -365,4 +365,13 @@ public class TempFileSystem extends NewVirtualFileSystem {
return false;
}
}
+
+ @Override
+ public int getBooleanAttributes(@NotNull VirtualFile file, int flags) {
+ FSItem item = convert(file);
+ int isDir = item instanceof FSDir ? BA_DIRECTORY : 0;
+ int exists = item == null ? 0 : BA_EXISTS;
+ int regular = isDir == 0 ? BA_REGULAR : 0;
+ return isDir | exists | regular;
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java
index 66d5eb272da9..abaac61050f4 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java
@@ -365,4 +365,22 @@ public class JarFileSystemImpl extends JarFileSystem implements ApplicationCompo
public VirtualFile refreshAndFindFileByPath(@NotNull String path) {
return VfsImplUtil.refreshAndFindFileByPath(this, path);
}
+
+ @Override
+ public int getBooleanAttributes(@NotNull VirtualFile file, int flags) {
+ int exists = 0;
+ JarHandler handler = getHandler(file);
+ if ((flags & BA_EXISTS) != 0) {
+ exists = handler.exists(file) ? BA_EXISTS : 0;
+ }
+ int isDir = 0;
+ if ((flags & BA_DIRECTORY) != 0) {
+ isDir = handler.isDirectory(file) ? BA_DIRECTORY : 0;
+ }
+ int regular = 0;
+ if ((flags & BA_REGULAR) != 0) {
+ regular = isDir == 0 ? BA_REGULAR : 0;
+ }
+ return exists | isDir | regular;
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java
index 915ca59e82b8..f727a8e7278f 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java
@@ -25,10 +25,7 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.*;
import com.intellij.openapi.vfs.ex.VirtualFileManagerEx;
-import com.intellij.openapi.vfs.newvfs.ManagingFS;
-import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
-import com.intellij.openapi.vfs.newvfs.RefreshQueue;
-import com.intellij.openapi.vfs.newvfs.VfsImplUtil;
+import com.intellij.openapi.vfs.newvfs.*;
import com.intellij.openapi.vfs.newvfs.impl.FakeVirtualFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Processor;
@@ -140,10 +137,6 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
private static final Method JAVA_IO_FILESYSTEM_GET_BOOLEAN_ATTRIBUTES_METHOD;
private static final Object/* java.io.FileSystem */ JAVA_IO_FILESYSTEM;
// copied from FileSystem
- private static final int BA_EXISTS = 0x01;
- private static final int BA_REGULAR = 0x02;
- private static final int BA_DIRECTORY = 0x04;
- private static final int BA_HIDDEN = 0x08;
static {
Object fs;
@@ -170,6 +163,8 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
JAVA_IO_FILESYSTEM_GET_BOOLEAN_ATTRIBUTES_METHOD = getBooleanAttributes;
}
+
+
@NotNull
private static File convertToIOFileAndCheck(@NotNull final VirtualFile file) throws FileNotFoundException {
final File ioFile = convertToIOFile(file);
@@ -769,6 +764,17 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
}
}
+ @Override
+ public int getBooleanAttributes(@NotNull VirtualFile file, int flags) {
+ int attributes = getBooleanAttributes(convertToIOFile(file));
+ if (attributes != -1) return attributes & flags;
+ return ((flags & BA_EXISTS) != 0 && exists(file) ? BA_EXISTS : 0) |
+ ((flags & BA_DIRECTORY) != 0 && isDirectory(file) ? BA_DIRECTORY : 0) |
+ ((flags & BA_REGULAR) != 0 && !isSpecialFile(file) ? BA_REGULAR : 0) |
+ ((flags & BA_HIDDEN) != 0 && convertToIOFile(file).isHidden() ? BA_HIDDEN : 0)
+ ;
+ }
+
@Override
public void refresh(final boolean asynchronous) {
RefreshQueue.getInstance().refresh(asynchronous, true, null, ManagingFS.getInstance().getRoots(this));
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/FileInfo.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/FileInfo.java
index ea85f580259f..52cdc416ac7f 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/FileInfo.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/FileInfo.java
@@ -15,23 +15,28 @@
*/
package com.intellij.openapi.vfs.impl.win32;
+import org.intellij.lang.annotations.MagicConstant;
+
/**
* @author Dmitry Avdeev
*/
public class FileInfo {
- static {
- initIDs();
- }
+ static {
+ initIDs();
+ }
- private static native void initIDs();
-
- public String name;
- public int attributes;
- public long timestamp;
- public long length;
+ private static native void initIDs();
- public String toString() {
- return name;
- }
+ public String name;
+
+ @MagicConstant(flagsFromClass = Win32Kernel.class)
+ public int attributes;
+
+ public long timestamp;
+ public long length;
+
+ public String toString() {
+ return name;
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32Kernel.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32Kernel.java
index c7fe8b9b2706..18450eb9ea6c 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32Kernel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32Kernel.java
@@ -15,7 +15,10 @@
*/
package com.intellij.openapi.vfs.impl.win32;
+import com.intellij.openapi.vfs.newvfs.NewVirtualFileSystem;
import com.intellij.util.ArrayUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.io.FileNotFoundException;
import java.util.ArrayList;
@@ -27,7 +30,10 @@ import java.util.Map;
*/
public class Win32Kernel {
public static final int FILE_ATTRIBUTE_READONLY = 0x0001;
+ public static final int FILE_ATTRIBUTE_HIDDEN = 0x0002;
public static final int FILE_ATTRIBUTE_DIRECTORY = 0x0010;
+ public static final int FILE_ATTRIBUTE_DEVICE = 0x0040;
+ public static final int FILE_ATTRIBUTE_REPARSE_POINT = 0x0400;
private final IdeaWin32 myKernel = new IdeaWin32();
@@ -43,13 +49,12 @@ public class Win32Kernel {
return ArrayUtil.EMPTY_STRING_ARRAY;
}
ArrayList names = new ArrayList(fileInfos.length);
- for (int i = 0, fileInfosLength = fileInfos.length; i < fileInfosLength; i++) {
- FileInfo info = fileInfos[i];
+ for (FileInfo info : fileInfos) {
if (info.name.equals(".")) {
myCache.put(absolutePath, info);
continue;
}
- else if (info.name.equals("..")) {
+ if (info.name.equals("..")) {
continue;
}
myCache.put(absolutePath + "/" + info.name, info);
@@ -59,8 +64,8 @@ public class Win32Kernel {
return ArrayUtil.toStringArray(names);
}
- public void exists(String path) throws FileNotFoundException {
- getInfo(path);
+ public boolean exists(String path) {
+ return doGetInfo(path) != null;
}
public boolean isDirectory(String path) throws FileNotFoundException {
@@ -84,14 +89,42 @@ public class Win32Kernel {
}
private FileInfo getInfo(String path) throws FileNotFoundException {
+ FileInfo info = doGetInfo(path);
+ if (info == null) {
+ throw new FileNotFoundException(path);
+ }
+ return info;
+ }
+
+ @Nullable
+ private FileInfo doGetInfo(String path) {
FileInfo info = myCache.get(path);
if (info == null) {
info = myKernel.getInfo(path.replace('/', '\\'));
if (info == null) {
- throw new FileNotFoundException(path);
+ return null;
}
myCache.put(path, info);
}
return info;
}
+
+ @NewVirtualFileSystem.FileBooleanAttributes
+ public int getBooleanAttributes(@NotNull String path, @NewVirtualFileSystem.FileBooleanAttributes int flags) {
+ FileInfo info = doGetInfo(path);
+ int result = 0;
+ if ((flags & NewVirtualFileSystem.BA_EXISTS) != 0) {
+ result |= info == null ? 0 : NewVirtualFileSystem.BA_EXISTS;
+ }
+ if ((flags & NewVirtualFileSystem.BA_DIRECTORY) != 0) {
+ result |= info == null || (info.attributes & FILE_ATTRIBUTE_DIRECTORY) == 0 ? 0 : NewVirtualFileSystem.BA_DIRECTORY;
+ }
+ if ((flags & NewVirtualFileSystem.BA_REGULAR) != 0) {
+ result |= info == null || (info.attributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_REPARSE_POINT)) != 0 ? 0 : NewVirtualFileSystem.BA_REGULAR;
+ }
+ if ((flags & NewVirtualFileSystem.BA_HIDDEN) != 0) {
+ result |= info == null || (info.attributes & FILE_ATTRIBUTE_HIDDEN) == 0 ? 0 : NewVirtualFileSystem.BA_HIDDEN;
+ }
+ return result;
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32LocalFileSystem.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32LocalFileSystem.java
index 126b8505ebe4..c69ca7f5379c 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32LocalFileSystem.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32LocalFileSystem.java
@@ -33,33 +33,34 @@ import java.util.Set;
public class Win32LocalFileSystem extends LocalFileSystemBase {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.impl.win32.Win32LocalFileSystem");
- private static boolean ourIsAvailable;
+ private static final boolean ourIsAvailable;
static {
+ boolean available = false;
if (SystemInfo.isWindows) {
String libName = SystemInfo.is64Bit ? "IdeaWin64" : "IdeaWin32";
try {
System.load(PathManager.getHomePath() + "/community/bin/win/" + libName + ".dll");
- ourIsAvailable = true;
+ available = true;
}
catch (Throwable t0) {
try {
System.load(PathManager.getHomePath() + "/bin/win/" + libName + ".dll");
- ourIsAvailable = true;
+ available = true;
}
catch (Throwable t1) {
try {
System.loadLibrary(libName);
- ourIsAvailable = true;
+ available = true;
}
catch (Throwable t2) {
LOG.warn("Failed to load native filesystem for Windows", t2);
- ourIsAvailable = false;
}
}
}
}
- if (ourIsAvailable) {
+ ourIsAvailable = available;
+ if (available) {
LOG.info("Native filesystem for Windows is operational");
}
}
@@ -108,16 +109,11 @@ public class Win32LocalFileSystem extends LocalFileSystemBase {
@Override
public boolean exists(@NotNull VirtualFile fileOrDirectory) {
if (fileOrDirectory.getParent() == null) return true;
- try {
- myKernel.exists(fileOrDirectory.getPath());
- if (checkMe && !super.exists(fileOrDirectory)) {
- LOG.error(fileOrDirectory.getPath());
- }
- return true;
- }
- catch (FileNotFoundException e) {
- return super.exists(fileOrDirectory);
+ boolean b = myKernel.exists(fileOrDirectory.getPath());
+ if (checkMe && b != super.exists(fileOrDirectory)) {
+ LOG.error(fileOrDirectory.getPath());
}
+ return b;
}
@Override
@@ -196,4 +192,9 @@ public class Win32LocalFileSystem extends LocalFileSystemBase {
public void removeWatchedRoot(@NotNull WatchRequest watchRequest) {
throw new UnsupportedOperationException();
}
+
+ @Override
+ public int getBooleanAttributes(@NotNull VirtualFile file, int flags) {
+ return myKernel.getBooleanAttributes(file.getPath(), flags);
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java
index 4e8508153bed..6ff87f199cb1 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java
@@ -42,6 +42,7 @@ import com.intellij.openapi.vfs.newvfs.events.VFileCreateEvent;
import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS;
import com.intellij.util.ArrayUtil;
import com.intellij.util.PathUtil;
+import com.intellij.util.SmartList;
import com.intellij.util.SystemProperties;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.text.CaseInsensitiveStringHashingStrategy;
@@ -312,14 +313,15 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
return VfsUtil.toVirtualFileArray(roots);
}
-
@Nullable
private VirtualFileSystemEntry createAndFindChildWithEventFire(@NotNull String name) {
final NewVirtualFileSystem delegate = getFileSystem();
VirtualFile fake = new FakeVirtualFile(this, name);
- if (delegate.exists(fake)) {
+ int attributes = delegate.getBooleanAttributes(fake, NewVirtualFileSystem.BA_EXISTS | NewVirtualFileSystem.BA_DIRECTORY);
+ if ((attributes & NewVirtualFileSystem.BA_EXISTS) != 0) {
final String realName = delegate.getCanonicallyCasedName(fake);
- VFileCreateEvent event = new VFileCreateEvent(null, this, realName, delegate.isDirectory(fake), true);
+ boolean isDir = (attributes & NewVirtualFileSystem.BA_DIRECTORY) != 0;
+ VFileCreateEvent event = new VFileCreateEvent(null, this, realName, isDir, true);
RefreshQueue.getInstance().processSingleEvent(event);
return findChild(realName);
}
@@ -526,14 +528,16 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
final Map map = asMap();
if (map == null) return Collections.emptyList();
- List names = new ArrayList();
+ List names = null;
+
for (Map.Entry entry : map.entrySet()) {
if (entry.getValue() == NULL_VIRTUAL_FILE) {
+ if (names == null) names = new SmartList();
names.add(entry.getKey());
}
}
- return names;
+ return names == null ? Collections.emptyList() : names;
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java
index 9a2de59babeb..0d387162d9fc 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java
@@ -48,6 +48,7 @@ import gnu.trove.TIntObjectHashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
import java.io.*;
import java.util.*;
@@ -189,7 +190,8 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
childrenIds[i] = currentIds[idx];
}
else {
- int childId = createAndCopyRecord(delegate, new FakeVirtualFile(file, name), id);
+ FakeVirtualFile child = new FakeVirtualFile(file, name);
+ int childId = createAndCopyRecord(delegate, child, id, delegate.isDirectory(child));
childrenIds[i] = childId;
}
}
@@ -283,12 +285,16 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
return FSRecords.getModCount();
}
- private static boolean copyRecordFromDelegateFS(final int id, final int parentId, final VirtualFile file, NewVirtualFileSystem delegate) {
+ private static boolean copyRecordFromDelegateFS(final int id,
+ final int parentId,
+ final VirtualFile file,
+ NewVirtualFileSystem delegate,
+ boolean isDir) {
String name = file.getName();
- if (name.length() > 0 && namesEqual(delegate, name, FSRecords.getName(id))) return false; // TODO: Handle root attributes change.
+ if (!name.isEmpty() && namesEqual(delegate, name, FSRecords.getName(id))) return false; // TODO: Handle root attributes change.
- if (name.length() == 0) { // TODO: hack
+ if (name.isEmpty()) { // TODO: hack
if (areChildrenLoaded(id)) return false;
}
@@ -299,11 +305,9 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
FSRecords.setTimestamp(id, delegate.getTimeStamp(file));
- boolean directory = delegate.isDirectory(file);
+ FSRecords.setLength(id, isDir ? -1L : delegate.getLength(file));
- FSRecords.setLength(id, directory ? -1L : delegate.getLength(file));
-
- FSRecords.setFlags(id, (directory ? IS_DIRECTORY_FLAG : 0) |
+ FSRecords.setFlags(id, (isDir ? IS_DIRECTORY_FLAG : 0) |
(delegate.isWritable(file) ? 0 : IS_READ_ONLY) |
(delegate.isSymLink(file) ? IS_SYMLINK : 0) |
(delegate.isSpecialFile(file) ? IS_SPECIAL : 0), true);
@@ -398,8 +402,10 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
}
VirtualFile fake = new FakeVirtualFile(parent, childName);
- if (delegate.exists(fake)) {
- int child = createAndCopyRecord(delegate, fake, parentId);
+ int attributes = delegate.getBooleanAttributes(fake, NewVirtualFileSystem.BA_EXISTS | NewVirtualFileSystem.BA_DIRECTORY);
+ if ((attributes & NewVirtualFileSystem.BA_EXISTS) != 0) {
+ boolean isDir = (attributes & NewVirtualFileSystem.BA_DIRECTORY) != 0;
+ int child = createAndCopyRecord(delegate, fake, parentId, isDir);
FSRecords.updateList(parentId, ArrayUtil.append(children, child));
return child;
}
@@ -722,13 +728,13 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
synchronized (LOCK) {
final String rootUrl = fs.getProtocol() + "://" + basePath;
VirtualFileSystemEntry root = myRoots.get(rootUrl);
- if (root == null && basePath.length() == 0) {
+ if (root == null && basePath.isEmpty()) {
root = myFakeRoot;
}
if (root == null) {
try {
final int rootId = FSRecords.findRootRecord(rootUrl);
- if (basePath.length() > 0) {
+ if (!basePath.isEmpty()) {
root = new VirtualDirectoryImpl(basePath, null, fs, rootId) {
@NotNull
@Override
@@ -756,14 +762,14 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
@Override
public VirtualFileSystemEntry findChild(@NotNull String name) {
- if (name.length() == 0) return null;
+ if (name.isEmpty()) return null;
return findRoot(name, fs);
}
};
}
if (!fs.exists(root)) return null;
- boolean newRoot = copyRecordFromDelegateFS(rootId, 0, root, fs);
+ boolean newRoot = copyRecordFromDelegateFS(rootId, 0, root, fs, true);
if (!newRoot) {
if (fs.getTimeStamp(root) != FSRecords.getTimestamp(rootId)) {
root.markDirtyRecursively();
@@ -774,7 +780,7 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
throw new RuntimeException(e);
}
- if (basePath.length() > 0) {
+ if (!basePath.isEmpty()) {
myRoots.put(rootUrl, root);
myRootsById.put(root.getId(), root);
}
@@ -949,10 +955,12 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
private static void executeCreateChild(final VirtualFile parent, final String name) {
final NewVirtualFileSystem delegate = getDelegate(parent);
- VirtualFile fakeFile = new FakeVirtualFile(parent, name);
- if (delegate.exists(fakeFile)) {
+ VirtualFile fake = new FakeVirtualFile(parent, name);
+ int attributes = delegate.getBooleanAttributes(fake, NewVirtualFileSystem.BA_EXISTS | NewVirtualFileSystem.BA_DIRECTORY);
+ if ((attributes & NewVirtualFileSystem.BA_EXISTS) != 0) {
final int parentId = getFileId(parent);
- int childId = createAndCopyRecord(delegate, fakeFile, parentId);
+ boolean isDir = (attributes & NewVirtualFileSystem.BA_DIRECTORY) != 0;
+ int childId = createAndCopyRecord(delegate, fake, parentId, isDir);
appendIdToParentList(parentId, childId);
final VirtualDirectoryImpl dir = (VirtualDirectoryImpl)parent;
@@ -960,9 +968,9 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
}
}
- private static int createAndCopyRecord(NewVirtualFileSystem delegateSystem, VirtualFile delegateFile, int parentId) {
+ private static int createAndCopyRecord(NewVirtualFileSystem delegateSystem, VirtualFile delegateFile, int parentId, boolean isDir) {
int childId = FSRecords.createRecord();
- copyRecordFromDelegateFS(childId, parentId, delegateFile, delegateSystem);
+ copyRecordFromDelegateFS(childId, parentId, delegateFile, delegateSystem, isDir);
return childId;
}
@@ -1067,7 +1075,7 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
FSRecords.setLength(getFileId(file), delegate.getLength(file));
FSRecords.setTimestamp(getFileId(file), delegate.getTimeStamp(file));
- ((NewVirtualFile)file).setModificationStamp(newModificationStamp);
+ ((VirtualFileSystemEntry)file).setModificationStamp(newModificationStamp);
}
@SuppressWarnings({"UnusedDeclaration"})
@@ -1092,6 +1100,7 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
return FSRecords.getName(id);
}
+ @TestOnly
public void cleanPersistedContents() {
try {
final int[] roots = FSRecords.listRoots();
@@ -1104,6 +1113,7 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
}
}
+ @TestOnly
private static void cleanPersistedContentsRecursively(int id) {
if (isDirectory(id)) {
for (int child : FSRecords.list(id)) {
@@ -1116,11 +1126,12 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
}
public static NewVirtualFileSystem replaceWithNativeFS(NewVirtualFileSystem delegate) {
- if (delegate.getProtocol().equals(LocalFileSystem.PROTOCOL) && Registry.is("filesystem.useNative")) {
- if (SystemInfo.isWindows && Win32LocalFileSystem.isAvailable()) {
- delegate = Win32LocalFileSystem.getWin32Instance();
- }
- }
+ if (delegate.getProtocol().equals(LocalFileSystem.PROTOCOL) &&
+ Registry.is("filesystem.useNative") &&
+ SystemInfo.isWindows &&
+ Win32LocalFileSystem.isAvailable()) {
+ delegate = Win32LocalFileSystem.getWin32Instance();
+ }
return delegate;
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/RefreshWorker.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/RefreshWorker.java
index 39f9da022ab9..9360c401f53d 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/RefreshWorker.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/RefreshWorker.java
@@ -25,6 +25,7 @@ import com.intellij.openapi.vfs.newvfs.impl.FakeVirtualFile;
import com.intellij.openapi.vfs.newvfs.impl.VirtualDirectoryImpl;
import com.intellij.openapi.vfs.newvfs.impl.VirtualFileSystemEntry;
import com.intellij.util.containers.Queue;
+import org.jetbrains.annotations.NotNull;
import java.util.*;
@@ -47,12 +48,15 @@ public class RefreshWorker {
public void scan() {
final NewVirtualFile root = (NewVirtualFile)myRefreshRoot;
NewVirtualFileSystem delegate = root.getFileSystem();
- if (root.isDirty() && !delegate.exists(root)) {
+ int attributes = delegate.getBooleanAttributes(root, NewVirtualFileSystem.BA_EXISTS | NewVirtualFileSystem.BA_DIRECTORY);
+
+ if (root.isDirty() && (attributes & NewVirtualFileSystem.BA_EXISTS) == 0) {
scheduleDeletion(root);
root.markClean();
}
else {
- if (root.isDirectory()) {
+ boolean isDir = (attributes & NewVirtualFileSystem.BA_DIRECTORY) != 0;
+ if (isDir) {
delegate = PersistentFS.replaceWithNativeFS(delegate);
}
@@ -86,14 +90,16 @@ public class RefreshWorker {
for (VirtualFile child : file.getChildren()) {
if (!deletedNames.contains(child.getName())) {
- scheduleChildRefresh(file, child, delegate);
+ int childAttributes = delegate.getBooleanAttributes(child, -1);
+ scheduleChildRefresh(file, child, delegate, childAttributes);
}
}
}
else {
for (VirtualFile child : file.getCachedChildren()) {
- if (delegate.exists(child)) {
- scheduleChildRefresh(file, child, delegate);
+ int childAttributes = delegate.getBooleanAttributes(child, -1);
+ if ((childAttributes & NewVirtualFileSystem.BA_EXISTS) != 0) {
+ scheduleChildRefresh(file, child, delegate, childAttributes);
}
else {
scheduleDeletion(child);
@@ -102,11 +108,13 @@ public class RefreshWorker {
final List names = dir.getSuspiciousNames();
for (String name : names) {
- if (name.length() == 0) continue;
+ if (name.isEmpty()) continue;
final VirtualFile fake = new FakeVirtualFile(file, name);
- if (delegate.exists(fake)) {
- scheduleCreation(file, name, delegate.isDirectory(fake));
+ int attrs = delegate.getBooleanAttributes(fake, NewVirtualFileSystem.BA_EXISTS | NewVirtualFileSystem.BA_DIRECTORY);
+ if ((attrs & NewVirtualFileSystem.BA_EXISTS) != 0) {
+ boolean isDira = (attrs & NewVirtualFileSystem.BA_DIRECTORY) != 0;
+ scheduleCreation(file, name, isDira);
}
}
}
@@ -132,13 +140,16 @@ public class RefreshWorker {
}
}
- private void scheduleChildRefresh(final VirtualFileSystemEntry file, final VirtualFile child, final NewVirtualFileSystem delegate) {
+ private void scheduleChildRefresh(@NotNull VirtualFileSystemEntry file,
+ @NotNull VirtualFile child,
+ @NotNull NewVirtualFileSystem delegate,
+ @NewVirtualFileSystem.FileBooleanAttributes int childAttributes) {
final boolean currentIsDirectory = child.isDirectory();
final boolean currentIsSymlink = child.isSymLink();
final boolean currentIsSpecial = child.isSpecialFile();
- final boolean upToDateIsDirectory = delegate.isDirectory(child);
+ final boolean upToDateIsDirectory = (childAttributes & NewVirtualFileSystem.BA_DIRECTORY) != 0;
final boolean upToDateIsSymlink = delegate.isSymLink(child);
- final boolean upToDateIsSpecial = delegate.isSpecialFile(child);
+ final boolean upToDateIsSpecial = (childAttributes & (NewVirtualFileSystem.BA_REGULAR | NewVirtualFileSystem.BA_DIRECTORY | NewVirtualFileSystem.BA_EXISTS)) == NewVirtualFileSystem.BA_EXISTS;
if (currentIsDirectory != upToDateIsDirectory || currentIsSymlink != upToDateIsSymlink || currentIsSpecial != upToDateIsSpecial) {
scheduleDeletion(child);
scheduleReCreation(file, child.getName(), upToDateIsDirectory);
diff --git a/platform/testFramework/src/com/intellij/mock/MockLocalFileSystem.java b/platform/testFramework/src/com/intellij/mock/MockLocalFileSystem.java
index 4fb4e5937362..59be016ec53c 100644
--- a/platform/testFramework/src/com/intellij/mock/MockLocalFileSystem.java
+++ b/platform/testFramework/src/com/intellij/mock/MockLocalFileSystem.java
@@ -251,4 +251,9 @@ public class MockLocalFileSystem extends LocalFileSystem {
public int getRank() {
return 1;
}
+
+ @Override
+ public int getBooleanAttributes(@NotNull VirtualFile file, int flags) {
+ return 0;
+ }
}
diff --git a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java
index 3ed50898fc01..c48b53e30bdc 100644
--- a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java
+++ b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java
@@ -41,7 +41,7 @@ import java.util.regex.Pattern;
@SuppressWarnings({"UtilityClassWithoutPrivateConstructor"})
public class FileUtil {
public static final int MEGABYTE = 1024 * 1024;
- public static final String ASYNC_DELETE_EXTENSION = ".__del__";
+ @NonNls public static final String ASYNC_DELETE_EXTENSION = ".__del__";
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.util.io.FileUtil");
@@ -681,7 +681,7 @@ public class FileUtil {
final int oldPermissions = FileSystemUtil.getPermissions(fromFile);
final int newPermissions = FileSystemUtil.getPermissions(toFile);
if (oldPermissions != -1 && newPermissions != -1) {
- FileSystemUtil.setPermissions(toFile, (oldPermissions | newPermissions));
+ FileSystemUtil.setPermissions(toFile, oldPermissions | newPermissions);
}
}
}
@@ -713,7 +713,7 @@ public class FileUtil {
public static void copyDir(@NotNull File fromDir, @NotNull File toDir, boolean copySystemFiles) throws IOException {
copyDir(fromDir, toDir, copySystemFiles ? null : new FileFilter() {
public boolean accept(File file) {
- return !file.getName().startsWith(".");
+ return !StringUtil.startsWithChar(file.getName(), '.');
}
});
}
@@ -939,7 +939,7 @@ public class FileUtil {
final StringBuilder builder = new StringBuilder(antPattern.length());
int asteriskCount = 0;
boolean recursive = true;
- final int start = ignoreStartingSlash && (antPattern.startsWith("/") || antPattern.startsWith("\\")) ? 1 : 0;
+ final int start = ignoreStartingSlash && (StringUtil.startsWithChar(antPattern, '/') || StringUtil.startsWithChar(antPattern, '\\')) ? 1 : 0;
for (int idx = start; idx < antPattern.length(); idx++) {
final char ch = antPattern.charAt(idx);