void (@NotNull FileType newFileType, @NotNull PluginDescriptor newPluginDescriptor, @NotNull List<? extends FileNameMatcher> newMatchers, boolean addScheme) { FileTypeWithDescriptor newFtd = new FileTypeWithDescriptor(newFileType, newPluginDescriptor); if (addScheme) { FileTypeWithDescriptor oldFileType = mySchemeManager.findSchemeByName(newFileType.getName()); if (oldFileType != null) { if (!(oldFileType.fileType instanceof AbstractFileType)) { throw new IllegalArgumentException(newFileType + " already registered"); } removeFromDuplicates(oldFileType.fileType, oldFileType.pluginDescriptor); } mySchemeManager.addScheme(newFtd); myPendingFileTypes.remove(newFileType.getName()); myPendingAssociations.removeAllAssociations(bean -> bean.name.equals(newFileType.getName())); checkFileTypeNamesUniqueness(newFtd); } List<FileNameMatcher> mappingsRemovedFromNew = myRemovedMappingTracker.getMappingsForFileType(newFileType.getName()); for (FileNameMatcher newMatcher : newMatchers) { if (mappingsRemovedFromNew.contains(newMatcher)) { continue; } FileTypeWithDescriptor oldFtd = myPatternsTable.findAssociatedFileType(newMatcher); List<FileNameMatcher> mappingsRemovedFromOld = oldFtd == null ? Collections.emptyList() : myRemovedMappingTracker.getMappingsForFileType(oldFtd.getName()); ConflictingFileTypeMappingTracker.ResolveConflictResult result; if (mappingsRemovedFromOld.contains(newMatcher)) { // no conflict really, new file type wins because removedMapping explicitly said "remove newMatcher from old file type" result = new ConflictingFileTypeMappingTracker.ResolveConflictResult(newFtd, "", "", true); } else { result = myConflictingMappingTracker.warnAndResolveConflict(newMatcher, oldFtd, newFtd); if (oldFtd != null) { LOG.debug(newMatcher + " had a conflict between " + oldFtd + " and " + newFtd + " and the winner is ... ... ... " + result); } } if (!result.approved() && myConflictResultConsumer != null) { myConflictResultConsumer.accept(result); } FileTypeWithDescriptor resolvedFtd = result.resolved(); FileType oldFileType = oldFtd == null ? null : oldFtd.fileType; if (!resolvedFtd.equals(oldFtd)) { myPatternsTable.addAssociation(newMatcher, resolvedFtd); if (result.approved() && oldFileType != null) { myRemovedMappingTracker.add(newMatcher, oldFileType.getName(), true); } } else if (oldFileType instanceof AbstractFileType && result.approved()) { myPatternsTable.addAssociation(newMatcher, newFtd); } myInitialAssociations.addAssociation(newMatcher, newFileType); } if (newFileType instanceof FileTypeIdentifiableByVirtualFile) { mySpecialFileTypes = ArrayUtil.append(mySpecialFileTypes, (FileTypeIdentifiableByVirtualFile)newFileType, FileTypeIdentifiableByVirtualFile.ARRAY_FACTORY); } PluginAdvertiserExtensionsStateService pluginAdvertiser = PluginAdvertiserExtensionsStateService.getInstance(); for (FileNameMatcher matcher : newMatchers) { pluginAdvertiser.registerLocalPlugin(matcher, newPluginDescriptor); } }