mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
several optimizations for speeding up getFileType() (part of IJPL-162944 speedup find usages in kotlin files):
- Do not query FileTypeOverrider extension point in hot path; store in fileTypeOverriderCache instead - Store FileTypeManager instance in FileTypeRegistry field to avoid indirection in hot path - Use fields to store some services queried in hot path - perform modifications under myPendingInitializationLock.writeLock() to avoid corruption GitOrigin-RevId: 9a6ec245f31a779542e2e830089573e8ce25333b
This commit is contained in:
committed by
intellij-monorepo-bot
parent
77000cdb9f
commit
92996cecaa
@@ -48,12 +48,11 @@ public class ApplicationManager {
|
||||
) {
|
||||
Application old = ourApplication;
|
||||
setApplication(instance);
|
||||
Supplier<? extends FileTypeRegistry> oldFileTypeRegistry = FileTypeRegistry.setInstanceSupplier(fileTypeRegistryGetter);
|
||||
FileTypeRegistry.setInstanceSupplier(fileTypeRegistryGetter, parent);
|
||||
Disposer.register(parent, () -> {
|
||||
if (old != null) {
|
||||
// to prevent NPEs in threads still running
|
||||
setApplication(old);
|
||||
FileTypeRegistry.setInstanceSupplier(oldFileTypeRegistry);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2,9 +2,12 @@
|
||||
package com.intellij.openapi.fileTypes;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.fileTypes.ex.FileTypeIdentifiableByVirtualFile;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.io.ByteSequence;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -31,18 +34,23 @@ import java.util.function.Supplier;
|
||||
* {@link com.intellij.openapi.application.ReadAction#nonBlocking}.
|
||||
*/
|
||||
public abstract class FileTypeRegistry {
|
||||
private static Supplier<? extends FileTypeRegistry> instanceGetter;
|
||||
private static volatile FileTypeRegistry instance;
|
||||
static {
|
||||
ApplicationManager.registerCleaner(() -> instance = null);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static Supplier<? extends FileTypeRegistry> setInstanceSupplier(@NotNull Supplier<? extends FileTypeRegistry> supplier) {
|
||||
Supplier<? extends FileTypeRegistry> oldValue = instanceGetter;
|
||||
instanceGetter = supplier;
|
||||
return oldValue;
|
||||
public static void setInstanceSupplier(@NotNull Supplier<? extends FileTypeRegistry> supplier, @NotNull Disposable parentDisposable) {
|
||||
FileTypeRegistry oldInstance = instance;
|
||||
instance = supplier.get();
|
||||
Disposer.register(parentDisposable, () -> {
|
||||
instance = oldInstance;
|
||||
});
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static boolean isInstanceSupplierSet() {
|
||||
return instanceGetter != null;
|
||||
return instance != null;
|
||||
}
|
||||
|
||||
public abstract boolean isFileIgnored(@NotNull VirtualFile file);
|
||||
@@ -59,13 +67,20 @@ public abstract class FileTypeRegistry {
|
||||
}
|
||||
|
||||
public static FileTypeRegistry getInstance() {
|
||||
Supplier<? extends FileTypeRegistry> instanceGetter = FileTypeRegistry.instanceGetter;
|
||||
if (instanceGetter == null) {
|
||||
// in tests FileTypeManager service maybe not preloaded, so, ourInstanceGetter is not set
|
||||
//noinspection deprecation
|
||||
return ApplicationManager.getApplication().getServiceByClassName("com.intellij.openapi.fileTypes.FileTypeManager");
|
||||
FileTypeRegistry cached = instance;
|
||||
if (cached == null) {
|
||||
// in tests FileTypeManager service maybe not preloaded, so, instance is not set
|
||||
Application application = ApplicationManager.getApplication();
|
||||
Class<? extends FileTypeRegistry> aClass = null;
|
||||
try {
|
||||
aClass = (Class<? extends FileTypeRegistry>)Class.forName("com.intellij.openapi.fileTypes.FileTypeManager");
|
||||
}
|
||||
catch (ClassNotFoundException ignored) {
|
||||
}
|
||||
instance = cached = application == null || aClass == null || !application.hasComponent(aClass)
|
||||
? new StubFileTypeRegistry() : application.getService(aClass);
|
||||
}
|
||||
return instanceGetter.get();
|
||||
return cached;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.openapi.fileTypes;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* Supplies empty {@link FileTypeRegistry} implementation when {@link com.intellij.openapi.fileTypes.FileTypeManager} is not available
|
||||
*/
|
||||
final class StubFileTypeRegistry extends FileTypeRegistry {
|
||||
@Override
|
||||
public @NotNull FileType getFileTypeByFileName(@NotNull String fileName) {
|
||||
return StubLanguageFileType.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull FileType getFileTypeByFile(@NotNull VirtualFile file) {
|
||||
return StubLanguageFileType.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull FileType getFileTypeByExtension(@NotNull String extension) {
|
||||
return StubLanguageFileType.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileType @NotNull [] getRegisteredFileTypes() {
|
||||
return new FileType[] {StubLanguageFileType.INSTANCE};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFileIgnored(@NotNull VirtualFile file) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable FileType findFileTypeByName(@NotNull String fileTypeName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final class StubLanguageFileType extends LanguageFileType {
|
||||
static final LanguageFileType INSTANCE = new StubLanguageFileType();
|
||||
|
||||
private StubLanguageFileType() {
|
||||
super(Language.ANY);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return "Mock";
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getDescription() {
|
||||
//noinspection HardCodedStringLiteral
|
||||
return "Mock";
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getDefaultExtension() {
|
||||
return ".mockExtensionThatProbablyWon'tEverExist";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1570,11 +1570,13 @@ com.intellij.openapi.fileTypes.FileTypeListener
|
||||
- fileTypesChanged(com.intellij.openapi.fileTypes.FileTypeEvent):V
|
||||
a:com.intellij.openapi.fileTypes.FileTypeManager
|
||||
- com.intellij.openapi.fileTypes.FileTypeRegistry
|
||||
- com.intellij.openapi.Disposable
|
||||
- sf:TOPIC:com.intellij.util.messages.Topic
|
||||
- <init>():V
|
||||
- p:<init>():V
|
||||
- a:associate(com.intellij.openapi.fileTypes.FileType,com.intellij.openapi.fileTypes.FileNameMatcher):V
|
||||
- f:associateExtension(com.intellij.openapi.fileTypes.FileType,java.lang.String):V
|
||||
- f:associatePattern(com.intellij.openapi.fileTypes.FileType,java.lang.String):V
|
||||
- dispose():V
|
||||
- a:getAssociations(com.intellij.openapi.fileTypes.FileType):java.util.List
|
||||
- a:getIgnoredFilesList():java.lang.String
|
||||
- s:getInstance():com.intellij.openapi.fileTypes.FileTypeManager
|
||||
@@ -1591,24 +1593,6 @@ c:com.intellij.openapi.fileTypes.FileTypes
|
||||
- sf:PLAIN_TEXT:com.intellij.openapi.fileTypes.LanguageFileType
|
||||
- sf:UNKNOWN:com.intellij.openapi.fileTypes.FileType
|
||||
- p:<init>():V
|
||||
f:com.intellij.openapi.fileTypes.MockFileTypeManager
|
||||
- com.intellij.openapi.fileTypes.FileTypeManager
|
||||
- <init>():V
|
||||
- associate(com.intellij.openapi.fileTypes.FileType,com.intellij.openapi.fileTypes.FileNameMatcher):V
|
||||
- findFileTypeByName(java.lang.String):com.intellij.openapi.fileTypes.FileType
|
||||
- getAssociations(com.intellij.openapi.fileTypes.FileType):java.util.List
|
||||
- getFileTypeByExtension(java.lang.String):com.intellij.openapi.fileTypes.FileType
|
||||
- getFileTypeByFile(com.intellij.openapi.vfs.VirtualFile):com.intellij.openapi.fileTypes.FileType
|
||||
- getFileTypeByFileName(java.lang.String):com.intellij.openapi.fileTypes.FileType
|
||||
- getIgnoredFilesList():java.lang.String
|
||||
- getKnownFileTypeOrAssociate(com.intellij.openapi.vfs.VirtualFile,com.intellij.openapi.project.Project):com.intellij.openapi.fileTypes.FileType
|
||||
- getRegisteredFileTypes():com.intellij.openapi.fileTypes.FileType[]
|
||||
- getStdFileType(java.lang.String):com.intellij.openapi.fileTypes.FileType
|
||||
- isFileIgnored(com.intellij.openapi.vfs.VirtualFile):Z
|
||||
- isFileIgnored(java.lang.String):Z
|
||||
- registerFileType(com.intellij.openapi.fileTypes.FileType,java.lang.String[]):V
|
||||
- removeAssociation(com.intellij.openapi.fileTypes.FileType,com.intellij.openapi.fileTypes.FileNameMatcher):V
|
||||
- setIgnoredFilesList(java.lang.String):V
|
||||
f:com.intellij.openapi.fileTypes.MockLanguageFileType
|
||||
- com.intellij.openapi.fileTypes.LanguageFileType
|
||||
- sf:INSTANCE:com.intellij.openapi.fileTypes.LanguageFileType
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.openapi.fileTypes;
|
||||
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.CachedSingletonsRegistry;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.messages.Topic;
|
||||
@@ -12,21 +10,11 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.model.fileTypes.FileNameMatcherFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Manages the relationship between filenames and {@link FileType} instances.
|
||||
*/
|
||||
public abstract class FileTypeManager extends FileTypeRegistry {
|
||||
static {
|
||||
FileTypeRegistry.setInstanceSupplier(FileTypeManager::getInstance);
|
||||
}
|
||||
|
||||
private static final Supplier<FileTypeManager> ourInstance = CachedSingletonsRegistry.lazy(() -> {
|
||||
Application app = ApplicationManager.getApplication();
|
||||
return app == null ? new MockFileTypeManager() : app.getService(FileTypeManager.class);
|
||||
});
|
||||
|
||||
public abstract class FileTypeManager extends FileTypeRegistry implements Disposable {
|
||||
@Topic.AppLevel
|
||||
public static final @NotNull Topic<FileTypeListener> TOPIC = new Topic<>(FileTypeListener.class, Topic.BroadcastDirection.TO_DIRECT_CHILDREN);
|
||||
|
||||
@@ -35,7 +23,15 @@ public abstract class FileTypeManager extends FileTypeRegistry {
|
||||
*/
|
||||
@SuppressWarnings("MethodOverridesStaticMethodOfSuperclass")
|
||||
public static FileTypeManager getInstance() {
|
||||
return ourInstance.get();
|
||||
FileTypeRegistry instance = FileTypeRegistry.getInstance();
|
||||
return instance instanceof FileTypeManager ftm ? ftm : new StubFileTypeManager();
|
||||
}
|
||||
|
||||
protected FileTypeManager() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
/** @deprecated use {@code com.intellij.fileType} extension point instead */
|
||||
|
||||
+4
-1
@@ -8,7 +8,10 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public final class MockFileTypeManager extends FileTypeManager {
|
||||
/**
|
||||
* empty implementation of {@link FileTypeManager} in case the {@link com.intellij.openapi.fileTypes.impl.FileTypeManagerImpl} is not available
|
||||
*/
|
||||
final class StubFileTypeManager extends FileTypeManager {
|
||||
@Override
|
||||
public @NotNull FileType getFileTypeByFileName(@NotNull String fileName) {
|
||||
return MockLanguageFileType.INSTANCE;
|
||||
@@ -12,9 +12,11 @@ import org.jetbrains.annotations.Nullable;
|
||||
* Substitutes type for files which users explicitly marked with "Override File Type" action
|
||||
*/
|
||||
final class UserFileTypeOverrider implements FileTypeOverrider {
|
||||
private final OverrideFileTypeManager myOverrideFileTypeManager = OverrideFileTypeManager.getInstance();
|
||||
|
||||
@Override
|
||||
public @Nullable FileType getOverriddenFileType(@NotNull VirtualFile file) {
|
||||
String overriddenType = OverrideFileTypeManager.getInstance().getFileValue(file);
|
||||
String overriddenType = myOverrideFileTypeManager.getFileValue(file);
|
||||
if (overriddenType != null) {
|
||||
return FileTypeManager.getInstance().findFileTypeByName(overriddenType);
|
||||
}
|
||||
|
||||
@@ -13423,12 +13423,10 @@ f:com.intellij.openapi.fileTypes.impl.FileTypeBean
|
||||
- setPluginDescriptor(com.intellij.openapi.extensions.PluginDescriptor):V
|
||||
c:com.intellij.openapi.fileTypes.impl.FileTypeManagerImpl
|
||||
- com.intellij.openapi.fileTypes.ex.FileTypeManagerEx
|
||||
- com.intellij.openapi.Disposable
|
||||
- com.intellij.openapi.components.PersistentStateComponent
|
||||
- com.intellij.openapi.extensions.ExtensionPointListener
|
||||
- p:<init>(kotlinx.coroutines.CoroutineScope):V
|
||||
- associate(com.intellij.openapi.fileTypes.FileType,com.intellij.openapi.fileTypes.FileNameMatcher):V
|
||||
- dispose():V
|
||||
- drainReDetectQueue():V
|
||||
- extensionAdded(com.intellij.openapi.fileTypes.impl.FileTypeBean,com.intellij.openapi.extensions.PluginDescriptor):V
|
||||
- extensionRemoved(com.intellij.openapi.fileTypes.impl.FileTypeBean,com.intellij.openapi.extensions.PluginDescriptor):V
|
||||
@@ -13461,7 +13459,6 @@ c:com.intellij.openapi.fileTypes.impl.FileTypeManagerImpl
|
||||
- registerFileType(com.intellij.openapi.fileTypes.FileType,java.lang.String[]):V
|
||||
- removeAssociation(com.intellij.openapi.fileTypes.FileType,com.intellij.openapi.fileTypes.FileNameMatcher):V
|
||||
- removePlainTextAssociationsForFile(java.lang.CharSequence):V
|
||||
- setConflictResultConsumer(java.util.function.Consumer):V
|
||||
- setIgnoredFilesList(java.lang.String):V
|
||||
- unregisterFileType(com.intellij.openapi.fileTypes.FileType,com.intellij.openapi.extensions.PluginDescriptor):V
|
||||
*:com.intellij.openapi.fileTypes.impl.FileTypeOverrider
|
||||
|
||||
@@ -3,11 +3,13 @@ package com.intellij.ide.plugins
|
||||
|
||||
import com.fasterxml.jackson.core.JsonFactory
|
||||
import com.fasterxml.jackson.core.JsonGenerator
|
||||
import com.intellij.openapi.application.*
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.application.ModernApplicationStarter
|
||||
import com.intellij.openapi.application.PathManager
|
||||
import com.intellij.openapi.diagnostic.logger
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager
|
||||
import com.intellij.openapi.fileTypes.PlainTextLikeFileType
|
||||
import com.intellij.openapi.progress.blockingContext
|
||||
import com.intellij.util.io.jackson.array
|
||||
import com.intellij.util.io.jackson.obj
|
||||
import com.intellij.util.lang.UrlClassLoader
|
||||
|
||||
+9
-2
@@ -3,6 +3,7 @@ package com.intellij.openapi.fileChooser.impl
|
||||
|
||||
import com.intellij.core.CoreFileTypeRegistry
|
||||
import com.intellij.ide.highlighter.ArchiveFileType
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.impl.LaterInvocator
|
||||
import com.intellij.openapi.command.CommandProcessorEx
|
||||
@@ -10,6 +11,7 @@ import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor
|
||||
import com.intellij.openapi.fileTypes.FileTypeRegistry
|
||||
import com.intellij.openapi.ui.Messages
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.NlsContexts
|
||||
import com.intellij.openapi.util.NlsSafe
|
||||
import com.intellij.openapi.util.SystemInfo
|
||||
@@ -30,7 +32,7 @@ import java.awt.KeyboardFocusManager
|
||||
import java.nio.file.FileSystems
|
||||
import java.nio.file.Path
|
||||
|
||||
internal class FileChooserDialogHelper(private val descriptor: FileChooserDescriptor) {
|
||||
internal class FileChooserDialogHelper(private val descriptor: FileChooserDescriptor) : Disposable {
|
||||
@Suppress("SpellCheckingInspection")
|
||||
private val ZIP_FS_TYPE = "zipfs"
|
||||
|
||||
@@ -46,10 +48,14 @@ internal class FileChooserDialogHelper(private val descriptor: FileChooserDescri
|
||||
val registry = CoreFileTypeRegistry()
|
||||
registry.registerFileType(ArchiveFileType.INSTANCE, "zip")
|
||||
registry.registerFileType(ArchiveFileType.INSTANCE, "jar")
|
||||
FileTypeRegistry.setInstanceSupplier { registry }
|
||||
FileTypeRegistry.setInstanceSupplier( { registry }, this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun dispose() {
|
||||
|
||||
}
|
||||
|
||||
fun setNativeDialogProperties() {
|
||||
if (SystemInfo.isWindows) {
|
||||
System.setProperty("sun.awt.windows.useCommonItemDialog", "true")
|
||||
@@ -74,6 +80,7 @@ internal class FileChooserDialogHelper(private val descriptor: FileChooserDescri
|
||||
IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown { previousFocusOwner.requestFocus() }
|
||||
}
|
||||
}
|
||||
Disposer.dispose(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+195
-134
@@ -49,13 +49,13 @@ import org.jdom.Element;
|
||||
import org.jetbrains.annotations.*;
|
||||
import org.jetbrains.jps.model.fileTypes.FileNameMatcherFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.function.Consumer;
|
||||
@@ -68,7 +68,7 @@ import static com.intellij.openapi.fileTypes.impl.AlarmAdapterKt.singleAlarm;
|
||||
storages = @Storage("filetypes.xml"),
|
||||
additionalExportDirectory = FileTypeManagerImpl.FILE_SPEC,
|
||||
category = SettingsCategory.CODE)
|
||||
public class FileTypeManagerImpl extends FileTypeManagerEx implements PersistentStateComponent<Element>, Disposable, ExtensionPointListener<FileTypeBean> {
|
||||
public class FileTypeManagerImpl extends FileTypeManagerEx implements PersistentStateComponent<Element>, ExtensionPointListener<FileTypeBean> {
|
||||
static final ExtensionPointName<FileTypeBean> EP_NAME = new ExtensionPointName<>("com.intellij.fileType");
|
||||
private static final Logger LOG = Logger.getInstance(FileTypeManagerImpl.class);
|
||||
|
||||
@@ -135,7 +135,9 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
|
||||
private final Map<String, StandardFileType> standardFileTypes = new LinkedHashMap<>();
|
||||
private final SchemeManager<FileTypeWithDescriptor> schemeManager;
|
||||
|
||||
protected FileTypeManagerImpl(@NotNull CoroutineScope coroutineScope) {
|
||||
protected FileTypeManagerImpl(@NotNull CoroutineScope coroutineScope) throws IOException {
|
||||
myDetectionService = new FileTypeDetectionService(this, coroutineScope);
|
||||
|
||||
NonLazySchemeProcessor<FileTypeWithDescriptor, FileTypeWithDescriptor> abstractTypesProcessor = new NonLazySchemeProcessor<>() {
|
||||
@Override
|
||||
public @NotNull FileTypeWithDescriptor readScheme(@NotNull Element element, boolean duringLoad) {
|
||||
@@ -198,14 +200,25 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
|
||||
}
|
||||
};
|
||||
schemeManager = SchemeManagerFactory.getInstance().create(FILE_SPEC, abstractTypesProcessor, null, null, SettingsCategory.CODE);
|
||||
|
||||
myDetectionService = new FileTypeDetectionService(this, coroutineScope);
|
||||
Disposer.register(this, myDetectionService);
|
||||
|
||||
EP_NAME.addExtensionPointListener(this, this);
|
||||
checkDuplicatedAlarm = singleAlarm(400, coroutineScope, this::checkUnique);
|
||||
EP_NAME.addExtensionPointListener(this, this);
|
||||
FileTypeOverrider.EP_NAME.addExtensionPointListener(new ExtensionPointListener<>() {
|
||||
@Override
|
||||
public void extensionAdded(FileTypeOverrider extension, @NotNull PluginDescriptor pluginDescriptor) {
|
||||
fileTypeOverriderCache = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void extensionRemoved(FileTypeOverrider extension, @NotNull PluginDescriptor pluginDescriptor) {
|
||||
fileTypeOverriderCache = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private FileTypeOverrider[] fileTypeOverriderCache;
|
||||
|
||||
public void extensionAdded(@NotNull FileTypeBean fileTypeBean, @NotNull PluginDescriptor pluginDescriptor) {
|
||||
fireBeforeFileTypesChanged();
|
||||
initializeMatchers(pluginDescriptor, fileTypeBean);
|
||||
@@ -363,6 +376,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
|
||||
|
||||
@TestOnly
|
||||
void clearStandardFileTypesBeforeTest() {
|
||||
assert ApplicationManager.getApplication().isUnitTestMode();
|
||||
myPendingInitializationLock.writeLock().lock();
|
||||
try {
|
||||
pendingAssociations.clear();
|
||||
@@ -473,22 +487,27 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
|
||||
}
|
||||
|
||||
private @NotNull FileType mergeOrInstantiateFileTypeBean(@NotNull FileTypeBean fileTypeBean) {
|
||||
StandardFileType type = withReadLock(() -> standardFileTypes.get(fileTypeBean.name));
|
||||
if (type == null) {
|
||||
return getFileTypeOrUnknown(instantiateFileTypeBean(fileTypeBean));
|
||||
myPendingInitializationLock.writeLock().lock();
|
||||
try {
|
||||
StandardFileType type = standardFileTypes.get(fileTypeBean.name);
|
||||
if (type == null) {
|
||||
return getFileTypeOrUnknown(instantiateFileTypeBean(fileTypeBean));
|
||||
}
|
||||
type.matchers.addAll(fileTypeBean.getMatchers());
|
||||
for (FileNameMatcher matcher : fileTypeBean.getMatchers()) {
|
||||
patternsTable.addAssociation(matcher, type.getDescriptor());
|
||||
}
|
||||
return type.fileType;
|
||||
}
|
||||
type.matchers.addAll(fileTypeBean.getMatchers());
|
||||
for (FileNameMatcher matcher : fileTypeBean.getMatchers()) {
|
||||
patternsTable.addAssociation(matcher, type.getDescriptor());
|
||||
finally {
|
||||
myPendingInitializationLock.writeLock().unlock();
|
||||
}
|
||||
return type.fileType;
|
||||
}
|
||||
|
||||
final Set<String> INSTANTIATED = PluginManagerCore.isUnitTestMode ? ContainerUtil.newConcurrentSet() : null;
|
||||
|
||||
private @Nullable FileTypeWithDescriptor instantiateFileTypeBean(@NotNull FileTypeBean bean) {
|
||||
Lock writeLock = myPendingInitializationLock.writeLock();
|
||||
writeLock.lock();
|
||||
myPendingInitializationLock.writeLock().lock();
|
||||
try {
|
||||
String fileTypeName = bean.name;
|
||||
// DCL
|
||||
@@ -569,7 +588,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
|
||||
return new FileTypeWithDescriptor(fileType, bean.getPluginDescriptor());
|
||||
}
|
||||
finally {
|
||||
writeLock.unlock();
|
||||
myPendingInitializationLock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -740,38 +759,44 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFileOfType(@NotNull VirtualFile file, @NotNull FileType requestedFileType) {
|
||||
public boolean isFileOfType(@NotNull VirtualFile virtualFile, @NotNull FileType requestedFileType) {
|
||||
//MAYBE RC: shouldn't we first check file.isValid() and return false eagerly?
|
||||
FileType temporarilyFixedFileType = getTemporarilyFixedFileType(file);
|
||||
FileType temporarilyFixedFileType = getTemporarilyFixedFileType(virtualFile);
|
||||
if (temporarilyFixedFileType != null) return temporarilyFixedFileType.equals(requestedFileType);
|
||||
|
||||
FileType overriddenFileType = FileTypeOverrider.EP_NAME.computeSafeIfAny(overrider -> overrider.getOverriddenFileType(file));
|
||||
if (overriddenFileType != null) {
|
||||
return overriddenFileType.equals(requestedFileType);
|
||||
FileTypeOverrider[] overriders = fileTypeOverriderCache;
|
||||
if (overriders == null) {
|
||||
fileTypeOverriderCache = overriders = FileTypeOverrider.EP_NAME.getExtensions();
|
||||
}
|
||||
for (FileTypeOverrider overrider : overriders) {
|
||||
FileType overriddenFileType = overrider.getOverriddenFileType(virtualFile);
|
||||
if (overriddenFileType != null) {
|
||||
return overriddenFileType.equals(requestedFileType);
|
||||
}
|
||||
}
|
||||
|
||||
if (file instanceof VirtualFileWithAssignedFileType) {
|
||||
FileType fileType = ((VirtualFileWithAssignedFileType)file).getAssignedFileType();
|
||||
if (virtualFile instanceof VirtualFileWithAssignedFileType) {
|
||||
FileType fileType = ((VirtualFileWithAssignedFileType)virtualFile).getAssignedFileType();
|
||||
if (fileType != null) {
|
||||
return fileType.equals(requestedFileType);
|
||||
}
|
||||
}
|
||||
|
||||
if (requestedFileType instanceof FileTypeIdentifiableByVirtualFile
|
||||
&& ((FileTypeIdentifiableByVirtualFile)requestedFileType).isMyFileType(file)) {
|
||||
&& ((FileTypeIdentifiableByVirtualFile)requestedFileType).isMyFileType(virtualFile)) {
|
||||
return true;
|
||||
}
|
||||
// otherwise, we can skip all the mySpecialFileTypes because it's certain this file type is not one of them
|
||||
|
||||
FileType fileType = getFileTypeByFileName(file.getNameSequence());
|
||||
FileType fileType = getFileTypeByFileName(virtualFile.getNameSequence());
|
||||
if (fileType == UnknownFileType.INSTANCE) {
|
||||
fileType = null;
|
||||
}
|
||||
if (fileType == null && file instanceof FakeVirtualFile && ScratchUtil.isScratch(file.getParent())) {
|
||||
if (fileType == null && virtualFile instanceof FakeVirtualFile && ScratchUtil.isScratch(virtualFile.getParent())) {
|
||||
return PlainTextFileType.INSTANCE.equals(requestedFileType);
|
||||
}
|
||||
if (fileType == null || fileType == DetectedByContentFileType.INSTANCE) {
|
||||
FileType detected = myDetectionService.getOrDetectFromContent(file, null, fileType);
|
||||
FileType detected = myDetectionService.getOrDetectFromContent(virtualFile, null, fileType);
|
||||
if (detected == UnknownFileType.INSTANCE && fileType == DetectedByContentFileType.INSTANCE) {
|
||||
return DetectedByContentFileType.INSTANCE.equals(requestedFileType);
|
||||
}
|
||||
@@ -805,27 +830,33 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public @NotNull FileType getFileTypeByFile(@NotNull VirtualFile file, byte @Nullable [] content) {
|
||||
FileType temporarilyFixedFileType = getTemporarilyFixedFileType(file);
|
||||
public @NotNull FileType getFileTypeByFile(@NotNull VirtualFile virtualFile, byte @Nullable [] content) {
|
||||
FileType temporarilyFixedFileType = getTemporarilyFixedFileType(virtualFile);
|
||||
if (temporarilyFixedFileType != null) return temporarilyFixedFileType;
|
||||
|
||||
FileType overriddenFileType = FileTypeOverrider.EP_NAME.computeSafeIfAny(overrider -> overrider.getOverriddenFileType(file));
|
||||
if (overriddenFileType != null) {
|
||||
return overriddenFileType;
|
||||
FileTypeOverrider[] overriders = fileTypeOverriderCache;
|
||||
if (overriders == null) {
|
||||
fileTypeOverriderCache = overriders = FileTypeOverrider.EP_NAME.getExtensions();
|
||||
}
|
||||
for (FileTypeOverrider overrider : overriders) {
|
||||
FileType overriddenFileType = overrider.getOverriddenFileType(virtualFile);
|
||||
if (overriddenFileType != null) {
|
||||
return overriddenFileType;
|
||||
}
|
||||
}
|
||||
|
||||
FileType fileType = getByFile(file);
|
||||
if (file instanceof StubVirtualFile) {
|
||||
if (fileType == null && content == null && file instanceof FakeVirtualFile) {
|
||||
if (ScratchUtil.isScratch(file.getParent())) return PlainTextFileType.INSTANCE;
|
||||
FileType fileType = getByFile(virtualFile);
|
||||
if (virtualFile instanceof StubVirtualFile) {
|
||||
if (fileType == null && content == null && virtualFile instanceof FakeVirtualFile) {
|
||||
if (ScratchUtil.isScratch(virtualFile.getParent())) return PlainTextFileType.INSTANCE;
|
||||
}
|
||||
}
|
||||
else if (fileType == null || fileType == DetectedByContentFileType.INSTANCE) {
|
||||
fileType = internalContinueToDetectFileTypeByFile(file, content, fileType);
|
||||
fileType = internalContinueToDetectFileTypeByFile(virtualFile, content, fileType);
|
||||
}
|
||||
FileType result = fileType == null ? UnknownFileType.INSTANCE : fileType;
|
||||
CachedFileTypes cached = CACHED;
|
||||
if (cached != null && file instanceof VirtualFileWithId vfid) {
|
||||
if (cached != null && virtualFile instanceof VirtualFileWithId vfid) {
|
||||
cached.fileTypes().put(vfid.getId(), result);
|
||||
}
|
||||
return result;
|
||||
@@ -840,8 +871,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
|
||||
|
||||
private FileType getTemporarilyFixedFileType(@NotNull VirtualFile file) {
|
||||
CachedFileTypes cached = CACHED;
|
||||
FileType fileType = cached != null && file instanceof VirtualFileWithId vfid ? cached.fileTypes().get(vfid.getId()) : null;
|
||||
return fileType;
|
||||
return cached != null && file instanceof VirtualFileWithId vfid ? cached.fileTypes().get(vfid.getId()) : null;
|
||||
}
|
||||
|
||||
// null means all conventional detect methods returned UnknownFileType.INSTANCE, have to detect from content
|
||||
@@ -1002,9 +1032,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
|
||||
FileTypeWithDescriptor ftd = FileTypeWithDescriptor.allFor(fileType);
|
||||
List<FileNameMatcher> matchers = patternsTable.getAssociations(ftd);
|
||||
// delete all records "extension xxx is removed from standard type X because the new fileType grabbed it to itself"
|
||||
removedMappingTracker.removeIf(mapping -> {
|
||||
return mapping.getFileTypeName().equals(fileType.getName()) || matchers.contains(mapping.getFileNameMatcher());
|
||||
});
|
||||
removedMappingTracker.removeIf(mapping -> mapping.getFileTypeName().equals(fileType.getName()) || matchers.contains(mapping.getFileNameMatcher()));
|
||||
patternsTable.removeAllAssociations(ftd);
|
||||
initialAssociations.removeAllAssociations(fileType);
|
||||
schemeManager.removeScheme(fileType.getName());
|
||||
@@ -1018,14 +1046,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
|
||||
|
||||
@Override
|
||||
public FileType @NotNull [] getRegisteredFileTypes() {
|
||||
instantiatePendingFileTypes();
|
||||
Collection<FileTypeWithDescriptor> descriptors = getAllFileTypeWithDescriptors();
|
||||
FileType[] result = new FileType[descriptors.size()];
|
||||
int i = 0;
|
||||
for (FileTypeManagerImpl.FileTypeWithDescriptor descriptor : descriptors) {
|
||||
result[i++] = descriptor.fileType();
|
||||
}
|
||||
return result;
|
||||
return ContainerUtil.map2Array(getRegisteredFileTypeWithDescriptors(), FileType.class, ftd->ftd.fileType);
|
||||
}
|
||||
|
||||
@NotNull List<FileTypeWithDescriptor> getRegisteredFileTypeWithDescriptors() {
|
||||
@@ -1326,65 +1347,67 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
|
||||
|
||||
@Override
|
||||
public @NotNull Element getState() {
|
||||
Element state = new Element("state");
|
||||
return withReadLock(() -> {
|
||||
Element state = new Element("state");
|
||||
|
||||
List<String> ignoreFiles = new ArrayList<>(ignoredPatterns.getIgnoreMasks());
|
||||
ignoreFiles.sort(null);
|
||||
if (!isEqualToDefaultIgnoreMasks(ignoreFiles)) {
|
||||
// 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, String.join(";", ignoreFiles)));
|
||||
}
|
||||
|
||||
Element extensionMap = new Element(ELEMENT_EXTENSION_MAP);
|
||||
|
||||
List<FileTypeWithDescriptor> notExternalizableFileTypes = new ArrayList<>();
|
||||
for (FileTypeWithDescriptor fileTypeDescriptor: getAllFileTypeWithDescriptors()) {
|
||||
if (!(fileTypeDescriptor.fileType() instanceof AbstractFileType) || defaultTypes.contains(fileTypeDescriptor)) {
|
||||
notExternalizableFileTypes.add(fileTypeDescriptor);
|
||||
List<String> ignoreFiles = new ArrayList<>(ignoredPatterns.getIgnoreMasks());
|
||||
ignoreFiles.sort(null);
|
||||
if (!isEqualToDefaultIgnoreMasks(ignoreFiles)) {
|
||||
// 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, String.join(";", ignoreFiles)));
|
||||
}
|
||||
}
|
||||
if (!notExternalizableFileTypes.isEmpty()) {
|
||||
notExternalizableFileTypes.sort(Comparator.comparing(it -> it.fileType().getName()));
|
||||
for (FileTypeWithDescriptor ftd : notExternalizableFileTypes) {
|
||||
writeExtensionsMap(extensionMap, ftd, true);
|
||||
}
|
||||
}
|
||||
|
||||
// https://youtrack.jetbrains.com/issue/IDEA-138366
|
||||
removedMappingTracker.save(extensionMap);
|
||||
Element extensionMap = new Element(ELEMENT_EXTENSION_MAP);
|
||||
|
||||
if (!unresolvedMappings.isEmpty()) {
|
||||
List<Map.Entry<FileNameMatcher, String>> entries = new ArrayList<>(unresolvedMappings.entrySet());
|
||||
entries.sort(Comparator.comparing(e -> e.getKey().getPresentableString()));
|
||||
for (Map.Entry<FileNameMatcher, String> entry : entries) {
|
||||
FileNameMatcher fileNameMatcher = entry.getKey();
|
||||
String typeName = entry.getValue();
|
||||
Element content = AbstractFileType.writeMapping(typeName, fileNameMatcher, true);
|
||||
if (content != null) {
|
||||
extensionMap.addContent(content);
|
||||
List<FileTypeWithDescriptor> notExternalizableFileTypes = new ArrayList<>();
|
||||
for (FileTypeWithDescriptor fileTypeDescriptor: getAllFileTypeWithDescriptors()) {
|
||||
if (!(fileTypeDescriptor.fileType() instanceof AbstractFileType) || defaultTypes.contains(fileTypeDescriptor)) {
|
||||
notExternalizableFileTypes.add(fileTypeDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!unresolvedHashBangs.isEmpty()) {
|
||||
List<Map.Entry<String, String>> entries = new ArrayList<>(unresolvedHashBangs.entrySet());
|
||||
entries.sort(Map.Entry.comparingByKey());
|
||||
|
||||
for (Map.Entry<String, String> entry : entries) {
|
||||
String pattern = entry.getKey();
|
||||
String typeName = entry.getValue();
|
||||
writeHashBang(extensionMap, pattern, typeName);
|
||||
if (!notExternalizableFileTypes.isEmpty()) {
|
||||
notExternalizableFileTypes.sort(Comparator.comparing(it -> it.fileType().getName()));
|
||||
for (FileTypeWithDescriptor ftd : notExternalizableFileTypes) {
|
||||
writeExtensionsMap(extensionMap, ftd, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!extensionMap.getChildren().isEmpty()) {
|
||||
state.addContent(extensionMap);
|
||||
}
|
||||
// https://youtrack.jetbrains.com/issue/IDEA-138366
|
||||
removedMappingTracker.save(extensionMap);
|
||||
|
||||
if (!state.getChildren().isEmpty()) {
|
||||
state.setAttribute(ATTRIBUTE_VERSION, String.valueOf(VERSION));
|
||||
}
|
||||
if (!unresolvedMappings.isEmpty()) {
|
||||
List<Map.Entry<FileNameMatcher, String>> entries = new ArrayList<>(unresolvedMappings.entrySet());
|
||||
entries.sort(Comparator.comparing(e -> e.getKey().getPresentableString()));
|
||||
for (Map.Entry<FileNameMatcher, String> entry : entries) {
|
||||
FileNameMatcher fileNameMatcher = entry.getKey();
|
||||
String typeName = entry.getValue();
|
||||
Element content = AbstractFileType.writeMapping(typeName, fileNameMatcher, true);
|
||||
if (content != null) {
|
||||
extensionMap.addContent(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!unresolvedHashBangs.isEmpty()) {
|
||||
List<Map.Entry<String, String>> entries = new ArrayList<>(unresolvedHashBangs.entrySet());
|
||||
entries.sort(Map.Entry.comparingByKey());
|
||||
|
||||
return state;
|
||||
for (Map.Entry<String, String> entry : entries) {
|
||||
String pattern = entry.getKey();
|
||||
String typeName = entry.getValue();
|
||||
writeHashBang(extensionMap, pattern, typeName);
|
||||
}
|
||||
}
|
||||
|
||||
if (!extensionMap.getChildren().isEmpty()) {
|
||||
state.addContent(extensionMap);
|
||||
}
|
||||
|
||||
if (!state.getChildren().isEmpty()) {
|
||||
state.setAttribute(ATTRIBUTE_VERSION, String.valueOf(VERSION));
|
||||
}
|
||||
|
||||
return state;
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean isEqualToDefaultIgnoreMasks(@NotNull List<String> newList) {
|
||||
@@ -1634,33 +1657,39 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
|
||||
if (isDefault && fileTypeDescr != null && fileTypeDescr.contains("syntax highlighting only")) {
|
||||
fileTypeDescr = fileTypeDescr.replace("syntax highlighting only", FileTypesBundle.message("filetype.default.syntax.highlighting.only.description"));
|
||||
}
|
||||
String iconPath = typeElement.getAttributeValue("icon");
|
||||
setFileTypeAttributes(type, fileTypeName, fileTypeDescr, iconPath);
|
||||
registerFileTypeWithoutNotification(type,
|
||||
pluginDescriptor,
|
||||
parseExtensions(context, extensionsStr),
|
||||
pluginAdvertiserExtensionsStateService,
|
||||
isDefault);
|
||||
myPendingInitializationLock.writeLock().lock();
|
||||
try {
|
||||
String iconPath = typeElement.getAttributeValue("icon");
|
||||
setFileTypeAttributes(type, fileTypeName, fileTypeDescr, iconPath);
|
||||
registerFileTypeWithoutNotification(type,
|
||||
pluginDescriptor,
|
||||
parseExtensions(context, extensionsStr),
|
||||
pluginAdvertiserExtensionsStateService,
|
||||
isDefault);
|
||||
|
||||
if (isDefault) {
|
||||
defaultTypes.add(new FileTypeWithDescriptor(type, pluginDescriptor));
|
||||
if (type instanceof ExternalizableFileType) {
|
||||
((ExternalizableFileType)type).markDefaultSettings();
|
||||
}
|
||||
}
|
||||
else {
|
||||
Element extensions = typeElement.getChild(ELEMENT_EXTENSION_MAP);
|
||||
if (extensions != null) {
|
||||
FileTypeWithDescriptor newFtd = new FileTypeWithDescriptor(type, pluginDescriptor);
|
||||
for (Pair<FileNameMatcher, String> association : AbstractFileType.readAssociations(extensions)) {
|
||||
associate(newFtd, association.getFirst(), false);
|
||||
}
|
||||
for (RemovedMappingTracker.RemovedMapping removedAssociation : RemovedMappingTracker.readRemovedMappings(extensions)) {
|
||||
removeAssociation(newFtd, removedAssociation.getFileNameMatcher(), false);
|
||||
if (isDefault) {
|
||||
defaultTypes.add(new FileTypeWithDescriptor(type, pluginDescriptor));
|
||||
if (type instanceof ExternalizableFileType) {
|
||||
((ExternalizableFileType)type).markDefaultSettings();
|
||||
}
|
||||
}
|
||||
else {
|
||||
Element extensions = typeElement.getChild(ELEMENT_EXTENSION_MAP);
|
||||
if (extensions != null) {
|
||||
FileTypeWithDescriptor newFtd = new FileTypeWithDescriptor(type, pluginDescriptor);
|
||||
for (Pair<FileNameMatcher, String> association : AbstractFileType.readAssociations(extensions)) {
|
||||
associate(newFtd, association.getFirst(), false);
|
||||
}
|
||||
for (RemovedMappingTracker.RemovedMapping removedAssociation : RemovedMappingTracker.readRemovedMappings(extensions)) {
|
||||
removeAssociation(newFtd, removedAssociation.getFileNameMatcher(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
finally {
|
||||
myPendingInitializationLock.writeLock().unlock();
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private @NotNull String filterAlreadyRegisteredExtensions(@NotNull String semicolonDelimited) {
|
||||
@@ -1705,9 +1734,6 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
|
||||
return patternsTable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() { }
|
||||
|
||||
void setPatternsTable(@NotNull Set<FileTypeWithDescriptor> fileTypes, @NotNull FileTypeAssocTable<FileTypeWithDescriptor> assocTable) {
|
||||
Map<FileNameMatcher, FileTypeWithDescriptor> removedMappings = getExtensionMap().getRemovedMappings(assocTable, fileTypes);
|
||||
String message = "set patterns table called: file types " + fileTypes + ", ass. table:" + assocTable;
|
||||
@@ -1770,15 +1796,21 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
|
||||
}
|
||||
|
||||
private void registerReDetectedMappings(@NotNull StandardFileType pair) {
|
||||
FileType fileType = pair.fileType;
|
||||
if (fileType == PlainTextFileType.INSTANCE) return;
|
||||
for (FileNameMatcher matcher : pair.matchers) {
|
||||
registerReDetectedMapping(fileType.getName(), matcher);
|
||||
if (matcher instanceof ExtensionFileNameMatcher extMatcher) {
|
||||
// also check exact file name matcher
|
||||
registerReDetectedMapping(fileType.getName(), new ExactFileNameMatcher("." + extMatcher.getExtension()));
|
||||
myPendingInitializationLock.writeLock().lock();
|
||||
try {
|
||||
FileType fileType = pair.fileType;
|
||||
if (fileType == PlainTextFileType.INSTANCE) return;
|
||||
for (FileNameMatcher matcher : pair.matchers) {
|
||||
registerReDetectedMapping(fileType.getName(), matcher);
|
||||
if (matcher instanceof ExtensionFileNameMatcher extMatcher) {
|
||||
// also check exact file name matcher
|
||||
registerReDetectedMapping(fileType.getName(), new ExactFileNameMatcher("." + extMatcher.getExtension()));
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
myPendingInitializationLock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private void registerReDetectedMapping(@NotNull String fileTypeName, @NotNull FileNameMatcher matcher) {
|
||||
@@ -1870,8 +1902,37 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
public void setConflictResultConsumer(@Nullable Consumer<? super ConflictingFileTypeMappingTracker.ResolveConflictResult> consumer) {
|
||||
void setConflictResultConsumer(@Nullable Consumer<? super ConflictingFileTypeMappingTracker.ResolveConflictResult> consumer) {
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode()) throw new IllegalStateException();
|
||||
conflictResultConsumer = consumer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + " FileTypeManagerImpl{" +
|
||||
"myDetectionService=" + myDetectionService +
|
||||
", CACHED=" + CACHED +
|
||||
", defaultTypes=" + defaultTypes +
|
||||
", specialFileTypes=" + Arrays.toString(specialFileTypes) +
|
||||
", patternsTable=" + patternsTable +
|
||||
", ignoredPatterns=" + ignoredPatterns +
|
||||
", myIgnoredFileCache=" + myIgnoredFileCache +
|
||||
", initialAssociations=" + initialAssociations +
|
||||
", unresolvedMappings=" + unresolvedMappings +
|
||||
", unresolvedHashBangs=" + unresolvedHashBangs +
|
||||
", removedMappingTracker=" + removedMappingTracker +
|
||||
", conflictingMappingTracker=" + conflictingMappingTracker +
|
||||
", pendingFileTypes=" + pendingFileTypes +
|
||||
", pendingAssociations=" + pendingAssociations +
|
||||
", myPendingInitializationLock=" + myPendingInitializationLock +
|
||||
", fileTypesPerPlugin=" + fileTypesPerPlugin +
|
||||
", checkDuplicatedAlarm=" + checkDuplicatedAlarm +
|
||||
", conflictResultConsumer=" + conflictResultConsumer +
|
||||
", standardFileTypes=" + standardFileTypes +
|
||||
", schemeManager=" + schemeManager +
|
||||
", fileTypeOverriderCache=" + Arrays.toString(fileTypeOverriderCache) +
|
||||
", INSTANTIATED=" + INSTANTIATED +
|
||||
", toLog=" + toLog +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import com.intellij.ide.highlighter.ArchiveFileType;
|
||||
import com.intellij.ide.highlighter.ModuleFileType;
|
||||
import com.intellij.ide.highlighter.ProjectFileType;
|
||||
import com.intellij.ide.highlighter.WorkspaceFileType;
|
||||
import com.intellij.ide.highlighter.custom.SyntaxTable;
|
||||
import com.intellij.ide.plugins.IdeaPluginDescriptorImpl;
|
||||
import com.intellij.ide.plugins.PluginDescriptorTestKt;
|
||||
import com.intellij.ide.plugins.PluginManagerCore;
|
||||
@@ -1086,7 +1085,6 @@ public class FileTypesTest extends HeavyPlatformTestCase {
|
||||
bean.setPluginDescriptor(pluginDescriptor);
|
||||
Disposable disposable = Disposer.newDisposable();
|
||||
WriteAction.run(() -> FileTypeManagerImpl.EP_NAME.getPoint().registerExtension(bean, disposable));
|
||||
((FileTypeManagerImpl)FileTypeManager.getInstance()).extensionRemoved(bean, pluginDescriptor); // avoid contamination of production FileTypeManager
|
||||
return disposable;
|
||||
}
|
||||
|
||||
@@ -1324,11 +1322,6 @@ public class FileTypesTest extends HeavyPlatformTestCase {
|
||||
assertInstanceOf(myFileTypeManager.getFileTypeByFileName("foo.hs"), MyHaskellFileType.class);
|
||||
|
||||
WriteAction.run(() -> Disposer.dispose(disposable));
|
||||
|
||||
// todo restore old AbstractFileType automatically?
|
||||
AbstractFileType old = new AbstractFileType(new SyntaxTable());
|
||||
old.setName(MyHaskellFileType.NAME);
|
||||
myFileTypeManager.registerFileType(old, List.of(), myFileTypeManager, FileTypeManagerImpl.coreIdeaPluginDescriptor());
|
||||
}
|
||||
|
||||
private static class MyCustomImageFileType implements FileType {
|
||||
|
||||
@@ -7,6 +7,7 @@ package org.toml.lang.psi
|
||||
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType
|
||||
import com.intellij.openapi.fileTypes.ex.FileTypeIdentifiableByVirtualFile
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import com.intellij.psi.tree.TokenSet
|
||||
@@ -27,7 +28,7 @@ object TomlFileType : LanguageFileType(TomlLanguage), FileTypeIdentifiableByVirt
|
||||
override fun getCharset(file: VirtualFile, content: ByteArray): String = "UTF-8"
|
||||
|
||||
override fun isMyFileType(file: VirtualFile): Boolean {
|
||||
return file.name == "config" && file.parent?.name == ".cargo"
|
||||
return StringUtil.equal(file.nameSequence, "config", true) && file.parent?.name == ".cargo"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user