use getVirtualFile(), getVirtualParent() instead of field access to ensure proper file type detection

This commit is contained in:
Alexey Kudravtsev
2013-06-05 11:49:10 +04:00
parent c3efb604a8
commit ee19cc4993
2 changed files with 88 additions and 92 deletions
@@ -51,6 +51,7 @@ public interface FilePath {
/** /**
* @return the file name (without directory component) * @return the file name (without directory component)
*/ */
@NotNull
String getName(); String getName();
String getPresentableUrl(); String getPresentableUrl();
@@ -73,10 +74,11 @@ public interface FilePath {
*/ */
FileType getFileType(); FileType getFileType();
void refresh(); VirtualFile refresh();
void hardRefresh(); void hardRefresh();
@NotNull
String getPath(); String getPath();
/** /**
@@ -91,7 +93,7 @@ public interface FilePath {
* @param strict if false, the method also returns true if files are equal * @param strict if false, the method also returns true if files are equal
* @return true if {@code this} file is ancestor of the {@code parent}. * @return true if {@code this} file is ancestor of the {@code parent}.
*/ */
boolean isUnder(FilePath parent, boolean strict); boolean isUnder(@NotNull FilePath parent, boolean strict);
/** /**
* @return the parent path or null if there are no parent * @return the parent path or null if there are no parent
@@ -64,7 +64,8 @@ public class FilePathImpl implements FilePath {
} }
} }
private static File fileFromVirtual(VirtualFile virtualParent, final VirtualFile child, String name) { @NotNull
private static File fileFromVirtual(VirtualFile virtualParent, final VirtualFile child, @NotNull String name) {
assert virtualParent != null || child != null; assert virtualParent != null || child != null;
if (virtualParent != null) { if (virtualParent != null) {
return new File(virtualParent.getPath(), name); return new File(virtualParent.getPath(), name);
@@ -72,22 +73,21 @@ public class FilePathImpl implements FilePath {
return new File(child.getPath()); return new File(child.getPath());
} }
private void detectFileType() { private static void detectFileType(VirtualFile virtualFile) {
VirtualFile file = myVirtualFile; if (virtualFile == null || !virtualFile.isValid() || virtualFile.isDirectory()) return;
if (file == null || !file.isValid() || file.isDirectory()) return; FileType fileType = virtualFile.getFileType();
FileType fileType = file.getFileType();
if (fileType == UnknownFileType.INSTANCE) { if (fileType == UnknownFileType.INSTANCE) {
FileTypeRegistry.getInstance().detectFileTypeFromContent(file); FileTypeRegistry.getInstance().detectFileTypeFromContent(virtualFile);
} }
} }
@Heavy @Heavy
public FilePathImpl(@NotNull VirtualFile virtualParent, String name, final boolean isDirectory) { public FilePathImpl(@NotNull VirtualFile virtualParent, @NotNull String name, final boolean isDirectory) {
this(virtualParent, name, isDirectory, null, false); this(virtualParent, name, isDirectory, null, false);
} }
@Heavy @Heavy
private FilePathImpl(@NotNull VirtualFile virtualParent, String name, final boolean isDirectory, final boolean forDeleted) { private FilePathImpl(@NotNull VirtualFile virtualParent, @NotNull String name, final boolean isDirectory, final boolean forDeleted) {
this(virtualParent, name, isDirectory, null, forDeleted); this(virtualParent, name, isDirectory, null, forDeleted);
} }
@@ -106,15 +106,15 @@ public class FilePathImpl implements FilePath {
this(virtualFile.getParent(), virtualFile.getName(), virtualFile.isDirectory(), virtualFile, false); this(virtualFile.getParent(), virtualFile.getName(), virtualFile.isDirectory(), virtualFile, false);
} }
@NotNull
public FilePath createChild(final String subPath, final boolean isDirectory) { public FilePath createChild(final String subPath, final boolean isDirectory) {
if (StringUtil.isEmptyOrSpaces(subPath)) return this; if (StringUtil.isEmptyOrSpaces(subPath)) return this;
if (getVirtualFile() != null && subPath.indexOf('/') == -1 && subPath.indexOf('\\') == -1) { VirtualFile virtualFile = getVirtualFile();
return new FilePathImpl(getVirtualFile(), subPath, isDirectory, true); if (virtualFile != null && subPath.indexOf('/') == -1 && subPath.indexOf('\\') == -1) {
} return new FilePathImpl(virtualFile, subPath, isDirectory, true);
else {
return new FilePathImpl(new File(getIOFile(), subPath), isDirectory);
} }
return new FilePathImpl(new File(getIOFile(), subPath), isDirectory);
} }
public int hashCode() { public int hashCode() {
@@ -125,11 +125,11 @@ public class FilePathImpl implements FilePath {
if (!(o instanceof FilePath)) { if (!(o instanceof FilePath)) {
return false; return false;
} }
else { if (!isSpecialName(myName) && !isSpecialName(((FilePath)o).getName()) &&
if (! isSpecialName(myName) && ! isSpecialName(((FilePath)o).getName()) && !Comparing.equal(myName, ((FilePath)o).getName())) {
! Comparing.equal(myName, ((FilePath)o).getName())) return false; return false;
return myFile.equals(((FilePath)o).getIOFile());
} }
return myFile.equals(((FilePath)o).getIOFile());
} }
private static boolean isSpecialName(final String name) { private static boolean isSpecialName(final String name) {
@@ -137,33 +137,33 @@ public class FilePathImpl implements FilePath {
} }
@Override @Override
public void refresh() { public VirtualFile refresh() {
VirtualFile virtualFile = myVirtualFile;
if (myLocal) { if (myLocal) {
if (myVirtualParent == null) { VirtualFile virtualParent = getVirtualFileParent();
myVirtualFile = LocalFileSystem.getInstance().findFileByIoFile(myFile); myVirtualFile = virtualFile = virtualParent == null ? LocalFileSystem.getInstance().findFileByIoFile(myFile) : virtualParent.findChild(myName);
}
else {
myVirtualFile = myVirtualParent.findChild(myName);
}
} }
return virtualFile;
} }
@Override @Override
public void hardRefresh() { public void hardRefresh() {
if (myLocal && (myVirtualFile == null || ! myVirtualFile.isValid())) { if (myLocal) {
myVirtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(myFile); VirtualFile virtualFile = getVirtualFile();
if (virtualFile == null || !virtualFile.isValid()) {
myVirtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(myFile);
}
} }
} }
@NotNull
@Override @Override
public String getPath() { public String getPath() {
final VirtualFile virtualFile = myVirtualFile; final VirtualFile virtualFile = getVirtualFile();
if (virtualFile != null && virtualFile.isValid()) { if (virtualFile != null && virtualFile.isValid()) {
return virtualFile.getPath(); return virtualFile.getPath();
} }
else { return myFile.getPath();
return myFile.getPath();
}
} }
public void setIsDirectory(boolean isDirectory) { public void setIsDirectory(boolean isDirectory) {
@@ -172,20 +172,17 @@ public class FilePathImpl implements FilePath {
@Override @Override
public boolean isDirectory() { public boolean isDirectory() {
if (myVirtualFile == null) { VirtualFile virtualFile = getVirtualFile();
return myIsDirectory; return virtualFile == null ? myIsDirectory : virtualFile.isDirectory();
}
else {
return myVirtualFile.isDirectory();
}
} }
@Override @Override
public boolean isUnder(FilePath parent, boolean strict) { public boolean isUnder(@NotNull FilePath parent, boolean strict) {
if (myVirtualFile != null) { VirtualFile virtualFile = getVirtualFile();
if (virtualFile != null) {
final VirtualFile parentFile = parent.getVirtualFile(); final VirtualFile parentFile = parent.getVirtualFile();
if (parentFile != null) { if (parentFile != null) {
return VfsUtilCore.isAncestor(parentFile, myVirtualFile, strict); return VfsUtilCore.isAncestor(parentFile, virtualFile, strict);
} }
} }
return FileUtil.isAncestor(parent.getIOFile(), getIOFile(), strict); return FileUtil.isAncestor(parent.getIOFile(), getIOFile(), strict);
@@ -193,8 +190,9 @@ public class FilePathImpl implements FilePath {
@Override @Override
public FilePath getParentPath() { public FilePath getParentPath() {
if (myVirtualParent != null && myVirtualParent.isValid() && myVirtualParent.getParent() != null) { VirtualFile virtualParent = getVirtualFileParent();
return new FilePathImpl(myVirtualParent); if (virtualParent != null && virtualParent.getParent() != null) {
return new FilePathImpl(virtualParent);
} }
// can't use File.getParentPath() because the path may not correspond to an actual file on disk, // can't use File.getParentPath() because the path may not correspond to an actual file on disk,
@@ -211,23 +209,25 @@ public class FilePathImpl implements FilePath {
@Override @Override
@Nullable @Nullable
public VirtualFile getVirtualFile() { public VirtualFile getVirtualFile() {
if (myVirtualFile != null && !myVirtualFile.isValid()) { VirtualFile virtualFile = myVirtualFile;
myVirtualFile = null; if (virtualFile != null && !virtualFile.isValid()) {
myVirtualFile = virtualFile = null;
} }
if (myVirtualFile == null) { if (virtualFile == null) {
refresh(); virtualFile = refresh();
} }
detectFileType(); detectFileType(virtualFile);
return myVirtualFile; return virtualFile;
} }
@Override @Override
@Nullable @Nullable
public VirtualFile getVirtualFileParent() { public VirtualFile getVirtualFileParent() {
if (myVirtualParent != null && !myVirtualParent.isValid()) { VirtualFile virtualParent = myVirtualParent;
myVirtualParent = null; if (virtualParent != null && !virtualParent.isValid()) {
myVirtualParent = virtualParent = null;
} }
return myVirtualParent; return virtualParent;
} }
@Override @Override
@@ -236,6 +236,7 @@ public class FilePathImpl implements FilePath {
return myFile; return myFile;
} }
@NotNull
@Override @Override
public String getName() { public String getName() {
return myName; return myName;
@@ -243,12 +244,11 @@ public class FilePathImpl implements FilePath {
@Override @Override
public String getPresentableUrl() { public String getPresentableUrl() {
if (myVirtualFile == null || !myVirtualFile.isValid()) { VirtualFile virtualFile = getVirtualFile();
if (virtualFile == null || !virtualFile.isValid()) {
return myFile.getAbsolutePath(); return myFile.getAbsolutePath();
} }
else { return virtualFile.getPresentableUrl();
return myVirtualFile.getPresentableUrl();
}
} }
@Override @Override
@@ -269,7 +269,8 @@ public class FilePathImpl implements FilePath {
@Override @Override
public Charset getCharset(Project project) { public Charset getCharset(Project project) {
// try to find existing virtual file // try to find existing virtual file
VirtualFile existing = myVirtualFile != null && myVirtualFile.isValid() ? myVirtualFile : null; VirtualFile virtualFile = getVirtualFile();
VirtualFile existing = virtualFile != null && virtualFile.isValid() ? virtualFile : null;
if (existing == null) { if (existing == null) {
LocalFileSystem lfs = LocalFileSystem.getInstance(); LocalFileSystem lfs = LocalFileSystem.getInstance();
for (File f = myFile; f != null; f = f.getParentFile()) { for (File f = myFile; f != null; f = f.getParentFile()) {
@@ -333,59 +334,52 @@ public class FilePathImpl implements FilePath {
if (virtualFileParent != null) { if (virtualFileParent != null) {
return new FilePathImpl(virtualFileParent, selectedFile.getName(), isDirectory, true); return new FilePathImpl(virtualFileParent, selectedFile.getName(), isDirectory, true);
} }
else { return new FilePathImpl(selectedFile, isDirectory);
return new FilePathImpl(selectedFile, isDirectory);
}
} }
public static FilePath createOn(String s) { public static FilePath createOn(@NotNull String s) {
File ioFile = new File(s); File ioFile = new File(s);
final LocalFileSystem localFileSystem = LocalFileSystem.getInstance(); final LocalFileSystem localFileSystem = LocalFileSystem.getInstance();
VirtualFile virtualFile = localFileSystem.findFileByIoFile(ioFile); VirtualFile virtualFile = localFileSystem.findFileByIoFile(ioFile);
if (virtualFile != null) { if (virtualFile != null) {
return new FilePathImpl(virtualFile); return new FilePathImpl(virtualFile);
} }
else { VirtualFile virtualFileParent = localFileSystem.findFileByIoFile(ioFile.getParentFile());
VirtualFile virtualFileParent = localFileSystem.findFileByIoFile(ioFile.getParentFile()); if (virtualFileParent == null) return null;
if (virtualFileParent != null) { return new FilePathImpl(virtualFileParent, ioFile.getName(), false);
return new FilePathImpl(virtualFileParent, ioFile.getName(), false);
}
else {
return null;
}
}
} }
private static Constructor<File> ourFileStringConstructor; private static final Constructor<File> ourFileStringConstructor;
private static boolean ourFileStringConstructorInitialized; static {
// avoid filename normalization (IDEADEV-10548)
Constructor<File> constructor = null; // new File(String, int)
try {
constructor = File.class.getDeclaredConstructor(String.class, int.class);
constructor.setAccessible(true);
}
catch (Exception ignored) {
}
ourFileStringConstructor = constructor;
}
@NotNull @NotNull
public static FilePath createNonLocal(String path, final boolean directory) { public static FilePath createNonLocal(@NotNull String path, final boolean directory) {
path = path.replace('/', File.separatorChar); path = path.replace('/', File.separatorChar);
// avoid filename normalization (IDEADEV-10548) File file = createIoFile(path);
if (!ourFileStringConstructorInitialized) { return new FilePathImpl(file, directory, false);
ourFileStringConstructorInitialized = true; }
@NotNull
private static File createIoFile(@NotNull String path) {
if (ourFileStringConstructor != null) {
try { try {
ourFileStringConstructor = File.class.getDeclaredConstructor(String.class, int.class); return ourFileStringConstructor.newInstance(path, 1);
ourFileStringConstructor.setAccessible(true);
} }
catch (Exception ex) { catch (Exception ex) {
ourFileStringConstructor = null; // reflection call failed, try regular call
} }
} }
File file = null; return new File(path);
try {
if (ourFileStringConstructor != null) {
file = ourFileStringConstructor.newInstance(path, 1);
}
}
catch (Exception ex) {
// reflection call failed, try regular call
}
if (file == null) {
file = new File(path);
}
return new FilePathImpl(file, directory, false);
} }
@Override @Override