diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java index ad56335f6aa8..16c1567ed63d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java @@ -24,7 +24,6 @@ import com.intellij.openapi.components.impl.stores.StateStorageManager.Externali import com.intellij.openapi.components.store.ReadOnlyModificationException; import com.intellij.openapi.components.store.StateStorageBase; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectBundle; @@ -282,8 +281,7 @@ public abstract class ComponentStoreImpl implements IComponentStore.Reloadable { } Class stateClass = ComponentSerializationUtil.getStateClass(component.getClass()); - T defaultState = getDefaultState(component, name, stateClass); - T state = defaultState; + T state = getDefaultState(component, name, stateClass); Storage[] storageSpecs = getComponentStorageSpecs(component, stateSpec, StateStorageOperation.READ); for (Storage storageSpec : storageSpecs) { @@ -296,10 +294,6 @@ public abstract class ComponentStoreImpl implements IComponentStore.Reloadable { } if (state != null) { - // quick dirty fix IDEA-136382 Bundled custom file types disappear - if (defaultState != state && component instanceof FileTypeManager) { - component.loadState(defaultState); - } component.loadState(state); } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileTypes/ex/FileTypeManagerEx.java b/platform/platform-impl/src/com/intellij/openapi/fileTypes/ex/FileTypeManagerEx.java index 3f4693c5ce14..d050fe760a7c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileTypes/ex/FileTypeManagerEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileTypes/ex/FileTypeManagerEx.java @@ -17,8 +17,6 @@ package com.intellij.openapi.fileTypes.ex; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.FileTypeManager; -import com.intellij.openapi.fileTypes.impl.AbstractFileType; -import com.intellij.openapi.options.SchemesManager; import org.jetbrains.annotations.NotNull; /** @@ -40,7 +38,4 @@ public abstract class FileTypeManagerEx extends FileTypeManager{ public abstract void fireFileTypesChanged(); public abstract void fireBeforeFileTypesChanged(); - - @NotNull - public abstract SchemesManager getSchemesManager(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java index cbf522b010f2..c2a03d709f47 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java @@ -18,6 +18,7 @@ package com.intellij.openapi.fileTypes.impl; import com.google.common.annotations.VisibleForTesting; import com.intellij.ide.highlighter.custom.SyntaxTable; import com.intellij.ide.plugins.PluginManager; +import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.impl.TransferToPooledThreadQueue; @@ -35,6 +36,7 @@ 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.util.text.StringUtilRt; import com.intellij.openapi.vfs.*; import com.intellij.openapi.vfs.newvfs.BulkFileListener; import com.intellij.openapi.vfs.newvfs.FileAttribute; @@ -47,6 +49,7 @@ import com.intellij.testFramework.LightVirtualFile; import com.intellij.util.*; import com.intellij.util.containers.ConcurrentPackedBitsArray; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.io.URLUtil; import com.intellij.util.messages.MessageBus; import com.intellij.util.messages.MessageBusConnection; import gnu.trove.THashMap; @@ -61,6 +64,7 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; +import java.net.URL; import java.nio.charset.Charset; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; @@ -81,6 +85,11 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent // then the value is null and autoDetectedAsText, autoDetectedAsBinary and autoDetectWasRun sets are used instead. private static final Key DETECTED_FROM_CONTENT_FILE_TYPE_KEY = Key.create("DETECTED_FROM_CONTENT_FILE_TYPE_KEY"); private static final int DETECT_BUFFER_SIZE = 8192; // the number of bytes to read from the file to feed to the file type detector + + @NonNls + private static final String DEFAULT_IGNORED = + "*.hprof;*.lib;*.pyc;*.pyo;*.rbc;*~;.DS_Store;.bundle;.git;.hg;.svn;CVS;RCS;SCCS;__pycache__;_svn;rcs;vssver.scc;vssver2.scc;"; + private static boolean RE_DETECT_ASYNC = !ApplicationManager.getApplication().isUnitTestMode(); private final Set myDefaultTypes = new THashSet(); private final List mySpecialFileTypes = new ArrayList(); @@ -210,6 +219,9 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent } }); + //noinspection SpellCheckingInspection + myIgnoredPatterns.setIgnoreMasks(DEFAULT_IGNORED); + // this should be done BEFORE reading state initStandardFileTypes(); } @@ -260,6 +272,27 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent for (StandardFileType pair : myStandardFileTypes.values()) { registerFileTypeWithoutNotification(pair.fileType, pair.matchers, true); } + + try { + URL defaultFileTypesUrl = FileTypeManagerImpl.class.getResource("/defaultFileTypes.xml"); + if (defaultFileTypesUrl != null) { + Element defaultFileTypesElement = JDOMUtil.load(URLUtil.openStream(defaultFileTypesUrl)); + for (Element e : defaultFileTypesElement.getChildren()) { + //noinspection SpellCheckingInspection + if ("filetypes".equals(e.getName())) { + for (Element element : e.getChildren(ELEMENT_FILETYPE)) { + loadFileType(element, true); + } + } + else if (AbstractFileType.ELEMENT_EXTENSION_MAP.equals(e.getName())) { + readGlobalMappings(e); + } + } + } + } + catch (Exception e) { + LOG.error(e); + } } private static boolean toLog() { @@ -346,10 +379,6 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent return stdFileType != null ? stdFileType.fileType : PlainTextFileType.INSTANCE; } - // ------------------------------------------------------------------------- - // ApplicationComponent interface implementation - // ------------------------------------------------------------------------- - @Override public void disposeComponent() { } @@ -375,10 +404,6 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent } } - // ------------------------------------------------------------------------- - // Implementation of abstract methods - // ------------------------------------------------------------------------- - @Override @NotNull public FileType getFileTypeByFileName(@NotNull String fileName) { @@ -550,7 +575,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent // TODO: Abstract file types are not std one, so need to be restored specially, // currently there are 6 of them and restoration does not happen very often so just iteration is enough if (type == PlainTextFileType.INSTANCE && !fileTypeName.equals(type.getName())) { - for (FileType fileType: getRegisteredFileTypes()) { + for (FileType fileType: mySchemesManager.getAllSchemes()) { if (fileTypeName.equals(fileType.getName())) { return fileType; } @@ -777,12 +802,6 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent myMessageBus.syncPublisher(TOPIC).beforeFileTypesChanged(event); } - @NotNull - @Override - public SchemesManager getSchemesManager() { - return mySchemesManager; - } - private final AtomicInteger fileTypeChangedCount = new AtomicInteger(); @Override public void fireFileTypesChanged() { @@ -791,7 +810,9 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent } private void clearCaches() { - autoDetectedAttribute = autoDetectedAttribute.newVersion(fileTypeChangedCount.incrementAndGet()); + int count = fileTypeChangedCount.incrementAndGet(); + autoDetectedAttribute = autoDetectedAttribute.newVersion(count); + PropertiesComponent.getInstance().setValue("fileTypeChangedCounter", Integer.toString(count)); packedFlags.clear(); } @@ -813,66 +834,62 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent } @Override - public void loadState(Element parentNode) { - int savedVersion = getVersion(parentNode); + public void loadState(Element state) { + int savedVersion = StringUtilRt.parseInt(state.getAttributeValue(ATTRIBUTE_VERSION), 0); String previousIgnores = getIgnoredFilesList(); - - for (Element e : parentNode.getChildren()) { - //noinspection SpellCheckingInspection - if ("filetypes".equals(e.getName())) { - for (Element element : e.getChildren(ELEMENT_FILETYPE)) { - loadFileType(element, true); - } + for (Element element : state.getChildren()) { + if (element.getName().equals(ELEMENT_IGNORE_FILES)) { + myIgnoredPatterns.setIgnoreMasks(element.getAttributeValue(ATTRIBUTE_LIST)); } - else if (ELEMENT_IGNORE_FILES.equals(e.getName())) { - myIgnoredPatterns.setIgnoreMasks(e.getAttributeValue(ATTRIBUTE_LIST)); + else if (AbstractFileType.ELEMENT_EXTENSION_MAP.equals(element.getName())) { + readGlobalMappings(element); } - else if (AbstractFileType.ELEMENT_EXTENSION_MAP.equals(e.getName())) { - readGlobalMappings(e); - } - } - - if (savedVersion == 0) { - addIgnore(".svn"); - } - if (savedVersion < 2) { - restoreStandardFileExtensions(); - } - if (savedVersion < 4) { - addIgnore("*.pyc"); - addIgnore("*.pyo"); - addIgnore(".git"); - } - if (savedVersion < 5) { - addIgnore("*.hprof"); - } - if (savedVersion < 6) { - addIgnore("_svn"); - } - - if (savedVersion < 7) { - addIgnore(".hg"); - } - - if (savedVersion < 8) { - addIgnore("*.lib"); - addIgnore("*~"); - } - - if (savedVersion < 9) { - addIgnore("__pycache__"); - } - - if (savedVersion < 10) { - addIgnore(".bundle"); } if (savedVersion < 11) { + if (savedVersion < 4) { + if (savedVersion == 0) { + addIgnore(".svn"); + } + + if (savedVersion < 2) { + restoreStandardFileExtensions(); + } + + addIgnore("*.pyc"); + addIgnore("*.pyo"); + addIgnore(".git"); + } + + if (savedVersion < 5) { + addIgnore("*.hprof"); + } + + if (savedVersion < 6) { + addIgnore("_svn"); + } + + if (savedVersion < 7) { + addIgnore(".hg"); + } + + if (savedVersion < 8) { + addIgnore("*.lib"); + addIgnore("*~"); + } + + if (savedVersion < 9) { + addIgnore("__pycache__"); + } + + if (savedVersion < 10) { + addIgnore(".bundle"); + } + addIgnore("*.rbc"); } - - if (savedVersion == 11 && PlatformUtils.isCLion()) { + else if (savedVersion == 11 && PlatformUtils.isCLion()) { // TODO During EAP CLion missed FileTypesManager.xml and users got empty excludes list // TODO this code is only necessary until CLion 1.0 is released, then can be safely deleted // previousIgnores come now from FileTypesManager.xml and merged with anything user may have added manually @@ -880,8 +897,12 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent } myIgnoredFileCache.clearCache(); - fileTypeChangedCount.set(JDOMExternalizer.readInteger(parentNode, "fileTypeChangedCounter", 0)); - autoDetectedAttribute = autoDetectedAttribute.newVersion(fileTypeChangedCount.get()); + + String counter = JDOMExternalizer.readString(state, "fileTypeChangedCounter"); + if (counter != null) { + fileTypeChangedCount.set(StringUtilRt.parseInt(counter, 0)); + autoDetectedAttribute = autoDetectedAttribute.newVersion(fileTypeChangedCount.get()); + } } private void readGlobalMappings(@NotNull Element e) { @@ -903,7 +924,6 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent } List> removedAssociations = AbstractFileType.readRemovedAssociations(e); - for (Trinity trinity : removedAssociations) { FileType type = getFileTypeByName(trinity.getSecond()); FileNameMatcher matcher = trinity.getFirst(); @@ -940,39 +960,43 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent } } - private static int getVersion(@NotNull Element node) { - final String verString = node.getAttributeValue(ATTRIBUTE_VERSION); - if (verString == null) return 0; - try { - return Integer.parseInt(verString); - } - catch (NumberFormatException e) { - return 0; - } - } - @Nullable @Override public Element getState() { Element state = new Element("state"); - state.setAttribute(ATTRIBUTE_VERSION, String.valueOf(VERSION)); - String ignoredFilesList = getIgnoredFilesList(); - if (!StringUtil.isEmpty(ignoredFilesList)) { - state.addContent(new Element(ELEMENT_IGNORE_FILES).setAttribute(ATTRIBUTE_LIST, ignoredFilesList)); + Set masks = myIgnoredPatterns.getIgnoreMasks(); + String ignoreFiles; + if (masks.isEmpty()) { + ignoreFiles = ""; + } + else { + String[] strings = ArrayUtil.toStringArray(masks); + Arrays.sort(strings); + ignoreFiles = StringUtil.join(strings, ";") + ";"; + } + + if (!ignoreFiles.equalsIgnoreCase(DEFAULT_IGNORED)) { + // empty means empty list - we need to distinguish null and empty to apply or not to apply default value + state.addContent(new Element(ELEMENT_IGNORE_FILES).setAttribute(ATTRIBUTE_LIST, ignoreFiles)); } Element map = new Element(AbstractFileType.ELEMENT_EXTENSION_MAP); - FileType[] fileTypes = getRegisteredFileTypes(); - if (fileTypes.length > 0) { - Arrays.sort(fileTypes, new Comparator() { + List notExternalizableFileTypes = new ArrayList(); + for (FileType type : mySchemesManager.getAllSchemes()) { + if (!(type instanceof AbstractFileType)) { + notExternalizableFileTypes.add(type); + } + } + if (!notExternalizableFileTypes.isEmpty()) { + Collections.sort(notExternalizableFileTypes, new Comparator() { @Override public int compare(@NotNull FileType o1, @NotNull FileType o2) { return o1.getName().compareTo(o2.getName()); } }); - for (FileType type : fileTypes) { + for (FileType type : notExternalizableFileTypes) { writeExtensionsMap(map, type, true); } } @@ -998,9 +1022,8 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent state.addContent(map); } - int value = fileTypeChangedCount.get(); - if (value != 0) { - JDOMExternalizer.write(state, "fileTypeChangedCounter", value); + if (!state.getChildren().isEmpty()) { + state.setAttribute(ATTRIBUTE_VERSION, String.valueOf(VERSION)); } return state; } diff --git a/platform/platform-resources/src/FileTypeManager.xml b/platform/platform-resources/src/defaultFileTypes.xml similarity index 100% rename from platform/platform-resources/src/FileTypeManager.xml rename to platform/platform-resources/src/defaultFileTypes.xml diff --git a/platform/testFramework/src/com/intellij/mock/MockFileTypeManager.java b/platform/testFramework/src/com/intellij/mock/MockFileTypeManager.java index 30e7f53d3a91..034cc3f92e2a 100644 --- a/platform/testFramework/src/com/intellij/mock/MockFileTypeManager.java +++ b/platform/testFramework/src/com/intellij/mock/MockFileTypeManager.java @@ -17,8 +17,6 @@ package com.intellij.mock; import com.intellij.openapi.fileTypes.*; import com.intellij.openapi.fileTypes.ex.FileTypeManagerEx; -import com.intellij.openapi.fileTypes.impl.AbstractFileType; -import com.intellij.openapi.options.SchemesManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ArrayUtil; @@ -180,12 +178,6 @@ public class MockFileTypeManager extends FileTypeManagerEx { } } - @NotNull - @Override - public SchemesManager getSchemesManager() { - return SchemesManager.EMPTY; - } - @Override public boolean isFileOfType(@NotNull VirtualFile file, @NotNull FileType type) { return false;