mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
re-detect file type on contents change
This commit is contained in:
@@ -78,7 +78,7 @@ public class FileTypeIndex extends ScalarIndexExtension<FileType>
|
||||
|
||||
@Override
|
||||
public boolean dependsOnFileContent() {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+66
-6
@@ -21,6 +21,7 @@ import com.intellij.ide.plugins.PluginManager;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.application.impl.TransferToPooledThreadQueue;
|
||||
import com.intellij.openapi.components.ExportableApplicationComponent;
|
||||
import com.intellij.openapi.components.RoamingType;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -37,16 +38,17 @@ import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.io.ByteSequence;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.openapi.vfs.VFileProperty;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileWithId;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
|
||||
import com.intellij.openapi.vfs.newvfs.FileAttribute;
|
||||
import com.intellij.openapi.vfs.newvfs.FileSystemInterface;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileCreateEvent;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
|
||||
import com.intellij.psi.SingleRootFileViewProvider;
|
||||
import com.intellij.testFramework.LightVirtualFile;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.containers.ConcurrentBitSet;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.messages.MessageBus;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
import gnu.trove.THashMap;
|
||||
@@ -112,9 +114,11 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
|
||||
|
||||
private final MessageBus myMessageBus;
|
||||
private final Map<String, StandardFileType> myStandardFileTypes = new LinkedHashMap<String, StandardFileType>();
|
||||
@NonNls private static final String[] FILE_TYPES_WITH_PREDEFINED_EXTENSIONS = {"JSP", "JSPX", "DTD", "HTML", "Properties", "XHTML"};
|
||||
@NonNls
|
||||
private static final String[] FILE_TYPES_WITH_PREDEFINED_EXTENSIONS = {"JSP", "JSPX", "DTD", "HTML", "Properties", "XHTML"};
|
||||
private final SchemesManager<FileType, AbstractFileType> mySchemesManager;
|
||||
@NonNls private static final String FILE_SPEC = "$ROOT_CONFIG$/filetypes";
|
||||
@NonNls
|
||||
private static final String FILE_SPEC = "$ROOT_CONFIG$/filetypes";
|
||||
private final ConcurrentBitSet autoDetectWasRun = new ConcurrentBitSet();
|
||||
private final ConcurrentBitSet autoDetectedAsText = new ConcurrentBitSet();
|
||||
private final ConcurrentBitSet autoDetectedAsBinary = new ConcurrentBitSet();
|
||||
@@ -238,6 +242,61 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
|
||||
fireFileTypesChanged();
|
||||
}
|
||||
}, RoamingType.PER_USER);
|
||||
bus.connect().subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener.Adapter(){
|
||||
@Override
|
||||
public void after(@NotNull List<? extends VFileEvent> events) {
|
||||
Set<VirtualFile> files = ContainerUtil.map2Set(events, new Function<VFileEvent, VirtualFile>() {
|
||||
@Override
|
||||
public VirtualFile fun(VFileEvent event) {
|
||||
VirtualFile file = event instanceof VFileCreateEvent ? null : event.getFile();
|
||||
return file != null && isDetectable(file) && wasAutoDetectedBefore(file) ? file : null;
|
||||
}
|
||||
});
|
||||
files.remove(null);
|
||||
reDetectQueue.offer(files);
|
||||
}
|
||||
});
|
||||
}
|
||||
private final TransferToPooledThreadQueue<Collection<VirtualFile>> reDetectQueue = new TransferToPooledThreadQueue<Collection<VirtualFile>>("file type re-detect", Condition.FALSE, -1, new Processor<Collection<VirtualFile>>() {
|
||||
@Override
|
||||
public boolean process(Collection<VirtualFile> files) {
|
||||
((FileTypeManagerImpl)getInstance()).reDetect(files);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
void drainReDetectQueue() {
|
||||
reDetectQueue.drain();
|
||||
}
|
||||
|
||||
private void reDetect(@NotNull Collection<VirtualFile> files) {
|
||||
final List<VirtualFile> changed = new ArrayList<VirtualFile>();
|
||||
for (VirtualFile file : files) {
|
||||
if (isDetectable(file) && wasAutoDetectedBefore(file)) {
|
||||
FileType before = file.getFileType();
|
||||
FileType after = detectFromContent(file);
|
||||
if (before != after) {
|
||||
changed.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!changed.isEmpty()) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FileContentUtilCore.reparseFiles(changed);
|
||||
}
|
||||
}, ApplicationManager.getApplication().getDisposed());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean wasAutoDetectedBefore(@NotNull VirtualFile file) {
|
||||
if (file.getUserData(DETECTED_FROM_CONTENT_FILE_TYPE_KEY) != null) return true;
|
||||
if (file instanceof VirtualFileWithId) {
|
||||
int id = Math.abs(((VirtualFileWithId)file).getId());
|
||||
// do not re-detect binary files
|
||||
return autoDetectWasRun.get(id) && !autoDetectedAsBinary.get(id);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void writeImportedExtensionsMap(final Element map, final ImportedFileType type) {
|
||||
@@ -394,6 +453,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
@Deprecated
|
||||
public FileType detectFileTypeFromContent(@NotNull VirtualFile file) {
|
||||
return file.getFileType();
|
||||
}
|
||||
|
||||
+49
-5
@@ -13,14 +13,19 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.fileTypes;
|
||||
package com.intellij.openapi.fileTypes.impl;
|
||||
|
||||
import com.intellij.ide.highlighter.ModuleFileType;
|
||||
import com.intellij.ide.highlighter.ProjectFileType;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileTypes.*;
|
||||
import com.intellij.openapi.fileTypes.ex.FileTypeManagerEx;
|
||||
import com.intellij.openapi.fileTypes.impl.FileTypeAssocTable;
|
||||
import com.intellij.openapi.util.io.ByteSequence;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
@@ -32,6 +37,9 @@ import com.intellij.psi.PsiPlainTextFile;
|
||||
import com.intellij.psi.impl.PsiManagerEx;
|
||||
import com.intellij.testFramework.PlatformTestCase;
|
||||
import com.intellij.util.PatternUtil;
|
||||
import junit.framework.TestCase;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -39,13 +47,13 @@ import java.util.Arrays;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class FileTypesTest extends PlatformTestCase {
|
||||
private FileTypeManagerEx myFileTypeManager;
|
||||
private FileTypeManagerImpl myFileTypeManager;
|
||||
private String myOldIgnoredFilesList;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
myFileTypeManager = FileTypeManagerEx.getInstanceEx();
|
||||
myFileTypeManager = (FileTypeManagerImpl)FileTypeManagerEx.getInstanceEx();
|
||||
myOldIgnoredFilesList = myFileTypeManager.getIgnoredFilesList();
|
||||
}
|
||||
|
||||
@@ -187,7 +195,7 @@ public class FileTypesTest extends PlatformTestCase {
|
||||
FileUtil.writeToFile(file, "xxx xxx xxx xxx");
|
||||
VirtualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
|
||||
assertNotNull(virtualFile);
|
||||
assertEquals(PlainTextFileType.INSTANCE, virtualFile.getFileType());
|
||||
TestCase.assertEquals(PlainTextFileType.INSTANCE, virtualFile.getFileType());
|
||||
}
|
||||
|
||||
public void testAutoDetectEmptyFile() throws IOException {
|
||||
@@ -253,4 +261,40 @@ public class FileTypesTest extends PlatformTestCase {
|
||||
|
||||
assertEquals(PlainTextFileType.INSTANCE, vFile.getFileType());
|
||||
}
|
||||
|
||||
public void testReDetectOnContentsChange() throws IOException {
|
||||
FileTypeRegistry.FileTypeDetector detector = new FileTypeRegistry.FileTypeDetector() {
|
||||
@Nullable
|
||||
@Override
|
||||
public FileType detect(@NotNull VirtualFile file, @NotNull ByteSequence firstBytes, @Nullable CharSequence firstCharsIfText) {
|
||||
String text = firstCharsIfText.toString();
|
||||
if (text.startsWith("TYPE:")) return FileTypeRegistry.getInstance().findFileTypeByName(StringUtil.trimStart(text, "TYPE:"));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVersion() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
Extensions.getRootArea().getExtensionPoint(FileTypeRegistry.FileTypeDetector.EP_NAME).registerExtension(detector);
|
||||
try {
|
||||
File d = createTempDirectory();
|
||||
File f = new File(d, "xx.asfdasdfas");
|
||||
FileUtil.writeToFile(f, "akjdhfksdjgf");
|
||||
VirtualFile vFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(f);
|
||||
assertTrue(vFile.getFileType().toString(), vFile.getFileType() instanceof PlainTextFileType);
|
||||
|
||||
VfsUtil.saveText(vFile, "TYPE:IDEA_MODULE");
|
||||
myFileTypeManager.drainReDetectQueue();
|
||||
assertTrue(vFile.getFileType().toString(), vFile.getFileType() instanceof ModuleFileType);
|
||||
|
||||
VfsUtil.saveText(vFile, "TYPE:IDEA_PROJECT");
|
||||
myFileTypeManager.drainReDetectQueue();
|
||||
assertTrue(vFile.getFileType().toString(), vFile.getFileType() instanceof ProjectFileType);
|
||||
}
|
||||
finally {
|
||||
Extensions.getRootArea().getExtensionPoint(FileTypeRegistry.FileTypeDetector.EP_NAME).unregisterExtension(detector);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user