loader = ServiceLoader.load(extensionClass, extensionClass.getClassLoader());
return ContainerUtil.newArrayList(loader);
}
+
+ @Override
+ public int getModificationStamp() {
+ return 0;
+ }
}
}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleRootModelSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleRootModelSerializer.java
index 76c8e7f9854e..e1fba4fecd75 100644
--- a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleRootModelSerializer.java
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleRootModelSerializer.java
@@ -31,7 +31,6 @@ import org.jetbrains.jps.model.library.sdk.JpsSdkType;
import org.jetbrains.jps.model.module.*;
import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension;
import org.jetbrains.jps.model.serialization.impl.JpsSerializationFormatException;
-import org.jetbrains.jps.model.serialization.java.JpsJavaModelSerializerExtension;
import org.jetbrains.jps.model.serialization.library.JpsLibraryTableSerializer;
import org.jetbrains.jps.model.serialization.library.JpsSdkTableSerializer;
@@ -178,8 +177,9 @@ public class JpsModuleRootModelSerializer {
@NotNull
private static JpsModuleSourceRootPropertiesSerializer> getSourceRootPropertiesSerializer(@NotNull Element sourceElement) {
String typeAttribute = sourceElement.getAttributeValue(SOURCE_ROOT_TYPE_ATTRIBUTE);
+ boolean forTests = Boolean.parseBoolean(sourceElement.getAttributeValue(IS_TEST_SOURCE_ATTRIBUTE));
if (typeAttribute == null) {
- typeAttribute = Boolean.parseBoolean(sourceElement.getAttributeValue(IS_TEST_SOURCE_ATTRIBUTE)) ? JAVA_TEST_ROOT_TYPE_ID : JAVA_SOURCE_ROOT_TYPE_ID;
+ typeAttribute = forTests ? JAVA_TEST_ROOT_TYPE_ID : JAVA_SOURCE_ROOT_TYPE_ID;
}
for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
for (JpsModuleSourceRootPropertiesSerializer> serializer : extension.getModuleSourceRootPropertiesSerializers()) {
@@ -189,7 +189,7 @@ public class JpsModuleRootModelSerializer {
}
}
LOG.warn("Unknown module source root type " + typeAttribute);
- return JpsJavaModelSerializerExtension.JAVA_SOURCE_ROOT_PROPERTIES_SERIALIZER;
+ return UnknownSourceRootPropertiesSerializer.forType(UnknownSourceRootType.getInstance(typeAttribute, forTests));
}
public static void saveRootModel(JpsModule module, Element rootModelElement) {
@@ -287,6 +287,9 @@ public class JpsModuleRootModelSerializer {
@Nullable
private static JpsModuleSourceRootPropertiesSerializer
getSerializer(JpsModuleSourceRootType
type) {
+ if (type instanceof UnknownSourceRootType) {
+ return (JpsModuleSourceRootPropertiesSerializer
)UnknownSourceRootPropertiesSerializer.forType((UnknownSourceRootType)type);
+ }
for (JpsModelSerializerExtension extension : JpsModelSerializerExtension.getExtensions()) {
for (JpsModuleSourceRootPropertiesSerializer> serializer : extension.getModuleSourceRootPropertiesSerializers()) {
if (serializer.getType().equals(type)) {
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/UnknownSourceRootPropertiesSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/UnknownSourceRootPropertiesSerializer.java
new file mode 100644
index 000000000000..1eccc5f860fc
--- /dev/null
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/UnknownSourceRootPropertiesSerializer.java
@@ -0,0 +1,36 @@
+// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package org.jetbrains.jps.model.serialization.module;
+
+import com.intellij.openapi.util.JDOMUtil;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.module.UnknownSourceRootType;
+import org.jetbrains.jps.model.module.UnknownSourceRootTypeProperties;
+
+public class UnknownSourceRootPropertiesSerializer extends JpsModuleSourceRootPropertiesSerializer> {
+ public UnknownSourceRootPropertiesSerializer(UnknownSourceRootType type) {
+ super(type, type.getUnknownTypeId());
+ }
+
+ @Override
+ public UnknownSourceRootTypeProperties loadProperties(@NotNull Element sourceRootTag) {
+ return new UnknownSourceRootTypeProperties<>(sourceRootTag.getParent() != null? sourceRootTag.clone() : sourceRootTag);
+ }
+
+ @Override
+ public void saveProperties(@NotNull UnknownSourceRootTypeProperties> properties, @NotNull Element sourceRootTag) {
+ Object data = properties.getPropertiesData();
+ if (data instanceof Element) {
+ JDOMUtil.copyMissingContent((Element)data, sourceRootTag);
+ }
+ }
+
+ public static UnknownSourceRootPropertiesSerializer forType(String unknownTypeId, boolean isTests) {
+ return forType(UnknownSourceRootType.getInstance(unknownTypeId, isTests));
+ }
+
+ @NotNull
+ public static UnknownSourceRootPropertiesSerializer forType(UnknownSourceRootType type) {
+ return new UnknownSourceRootPropertiesSerializer(type);
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/jps/impl/JpsIdePluginManagerImpl.java b/platform/platform-impl/src/com/intellij/jps/impl/JpsIdePluginManagerImpl.java
index 6a32247cc42a..52bc551d9246 100644
--- a/platform/platform-impl/src/com/intellij/jps/impl/JpsIdePluginManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/jps/impl/JpsIdePluginManagerImpl.java
@@ -2,8 +2,26 @@
package com.intellij.jps.impl;
import com.intellij.openapi.extensions.*;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.project.ProjectManager;
+import com.intellij.openapi.roots.ContentEntry;
+import com.intellij.openapi.roots.ModuleRootModificationUtil;
+import com.intellij.openapi.roots.SourceFolder;
+import com.intellij.openapi.util.Ref;
import com.intellij.util.containers.ContainerUtil;
+import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
+import org.jetbrains.jps.model.module.UnknownSourceRootType;
+import org.jetbrains.jps.model.module.UnknownSourceRootTypeProperties;
+import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension;
+import org.jetbrains.jps.model.serialization.module.JpsModuleRootModelSerializer;
+import org.jetbrains.jps.model.serialization.module.JpsModuleSourceRootPropertiesSerializer;
+import org.jetbrains.jps.model.serialization.module.UnknownSourceRootPropertiesSerializer;
import org.jetbrains.jps.plugin.JpsPluginManager;
import java.io.BufferedReader;
@@ -13,9 +31,11 @@ import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicInteger;
public final class JpsIdePluginManagerImpl extends JpsPluginManager {
private final List myExternalBuildPlugins = new CopyOnWriteArrayList<>();
+ private final AtomicInteger myModificationStamp = new AtomicInteger(0);
public JpsIdePluginManagerImpl() {
ExtensionsArea rootArea = Extensions.getRootArea();
@@ -25,30 +45,191 @@ public final class JpsIdePluginManagerImpl extends JpsPluginManager {
//todo[nik] get rid of this check: currently this class is used in intellij.platform.jps.build tests instead of JpsPluginManagerImpl because intellij.platform.ide.impl module is added to classpath via testFramework
if (rootArea.hasExtensionPoint(JpsPluginBean.EP_NAME)) {
+ final Ref initial = new Ref<>(Boolean.TRUE);
JpsPluginBean.EP_NAME.getPoint(null).addExtensionPointListener(new ExtensionPointListener() {
@Override
public void extensionAdded(@NotNull JpsPluginBean extension, @NotNull PluginDescriptor pluginDescriptor) {
- ContainerUtil.addIfNotNull(myExternalBuildPlugins, pluginDescriptor);
+ if (initial.get()) {
+ myExternalBuildPlugins.add(pluginDescriptor);
+ }
+ else {
+ handlePluginAdded(pluginDescriptor);
+ }
+ }
+
+ @Override
+ public void extensionRemoved(@NotNull JpsPluginBean extension, @NotNull PluginDescriptor pluginDescriptor) {
+ handlePluginRemoved(pluginDescriptor);
}
}, true, null);
+ initial.set(Boolean.FALSE);
}
if (rootArea.hasExtensionPoint("com.intellij.compileServer.plugin")) {
ExtensionPoint extensionPoint = rootArea.getExtensionPoint("com.intellij.compileServer.plugin");
+ final Ref initial = new Ref<>(Boolean.TRUE);
//noinspection unchecked
extensionPoint.addExtensionPointListener(new ExtensionPointListener() {
@Override
public void extensionAdded(@NotNull Object extension, @NotNull PluginDescriptor pluginDescriptor) {
- ContainerUtil.addIfNotNull(myExternalBuildPlugins, pluginDescriptor);
+ if (initial.get()) {
+ myExternalBuildPlugins.add(pluginDescriptor);
+ }
+ else {
+ handlePluginAdded(pluginDescriptor);
+ }
+ }
+
+ @Override
+ public void extensionRemoved(@NotNull Object extension, @NotNull PluginDescriptor pluginDescriptor) {
+ handlePluginRemoved(pluginDescriptor);
}
}, true, null);
+ initial.set(Boolean.FALSE);
}
}
+ private void handlePluginRemoved(@NotNull PluginDescriptor pluginDescriptor) {
+ Map, JpsModuleSourceRootPropertiesSerializer>> removed = new HashMap<>();
+ for (JpsModelSerializerExtension extension : loadExtensions(JpsModelSerializerExtension.class)) {
+ for (JpsModuleSourceRootPropertiesSerializer> serializer : extension.getModuleSourceRootPropertiesSerializers()) {
+ removed.put(serializer.getType(), serializer);
+ }
+ }
+
+ if (myExternalBuildPlugins.remove(pluginDescriptor)) {
+ myModificationStamp.incrementAndGet();
+ }
+ else{
+ return;
+ }
+
+ for (JpsModelSerializerExtension extension : loadExtensions(JpsModelSerializerExtension.class)) {
+ for (JpsModuleSourceRootPropertiesSerializer> serializer : extension.getModuleSourceRootPropertiesSerializers()) {
+ removed.remove(serializer.getType());
+ }
+ }
+
+ if (!removed.isEmpty()) {
+ for (Project project : ProjectManager.getInstance().getOpenProjects()) {
+ replaceWithUnknownRootType(project, removed.values());
+ }
+ }
+ }
+
+ private void handlePluginAdded(@NotNull PluginDescriptor pluginDescriptor) {
+ if (myExternalBuildPlugins.contains(pluginDescriptor)) {
+ return;
+ }
+ Set before = new HashSet<>();
+ for (JpsModelSerializerExtension extension : loadExtensions(JpsModelSerializerExtension.class)) {
+ for (JpsModuleSourceRootPropertiesSerializer> serializer : extension.getModuleSourceRootPropertiesSerializers()) {
+ before.add(serializer.getTypeId());
+ }
+ }
+
+ myExternalBuildPlugins.add(pluginDescriptor);
+ myModificationStamp.incrementAndGet();
+
+ Map> added = new HashMap<>();
+ for (JpsModelSerializerExtension extension : loadExtensions(JpsModelSerializerExtension.class)) {
+ for (JpsModuleSourceRootPropertiesSerializer> serializer : extension.getModuleSourceRootPropertiesSerializers()) {
+ added.put(serializer.getTypeId(), serializer);
+ }
+ }
+ added.keySet().removeAll(before);
+
+ if (!added.isEmpty()) {
+ for (Project project : ProjectManager.getInstance().getOpenProjects()) {
+ updateCustomRootTypes(project, added.values());
+ }
+ }
+ }
+
+ public static void replaceWithUnknownRootType(Project project, Collection> unregisteredSerializers) {
+ if (unregisteredSerializers.isEmpty()) {
+ return;
+ }
+ Map, JpsModuleSourceRootPropertiesSerializer>> serializers = new HashMap<>();
+ for (JpsModuleSourceRootPropertiesSerializer> serializer : unregisteredSerializers) {
+ serializers.put(serializer.getType(), serializer);
+ }
+ for (Module module : ModuleManager.getInstance(project).getModules()) {
+ ModuleRootModificationUtil.modifyModel(module, model -> {
+ boolean shouldCommit = false;
+ for (ContentEntry contentEntry : model.getContentEntries()) {
+ for (SourceFolder folder : contentEntry.getSourceFolders()) {
+ JpsModuleSourceRootPropertiesSerializer> removedSerializer = serializers.get(folder.getRootType());
+ if (removedSerializer != null) {
+ changeType(
+ folder,
+ UnknownSourceRootPropertiesSerializer.forType(removedSerializer.getTypeId(), folder.getRootType().isForTests()),
+ serializeProperties(folder, removedSerializer)
+ );
+ shouldCommit = true;
+ }
+ }
+ }
+ return shouldCommit;
+ });
+ }
+ }
+
+ public static void updateCustomRootTypes(Project project, Collection> registeredSerializers) {
+ if (registeredSerializers.isEmpty()) {
+ return;
+ }
+ Map> serializers = new HashMap<>();
+ for (JpsModuleSourceRootPropertiesSerializer> ser : registeredSerializers) {
+ serializers.put(ser.getTypeId(), ser);
+ }
+ for (Module module : ModuleManager.getInstance(project).getModules()) {
+ ModuleRootModificationUtil.modifyModel(module, model -> {
+ boolean shouldCommit = false;
+ for (ContentEntry contentEntry : model.getContentEntries()) {
+ for (SourceFolder folder : contentEntry.getSourceFolders()) {
+ if (folder.getRootType() instanceof UnknownSourceRootType) {
+ UnknownSourceRootType type = (UnknownSourceRootType)folder.getRootType();
+ JpsModuleSourceRootPropertiesSerializer> serializer = serializers.get(type.getUnknownTypeId());
+ if (serializer != null) {
+ UnknownSourceRootTypeProperties> properties = folder.getJpsElement().getProperties(type);
+ Object data = properties != null? properties.getPropertiesData() : null;
+ changeType(folder, serializer, data instanceof Element ? (Element)data : null);
+ shouldCommit = true;
+ }
+ }
+ }
+ }
+ return shouldCommit;
+ });
+ }
+ }
+
+ @Nullable
+ private static Element serializeProperties(SourceFolder root, @NotNull JpsModuleSourceRootPropertiesSerializer
serializer) {
+ P properties = root.getJpsElement().getProperties(serializer.getType());
+ if (properties != null) {
+ Element sourceElement = new Element(JpsModuleRootModelSerializer.SOURCE_FOLDER_TAG);
+ serializer.saveProperties(properties, sourceElement);
+ return sourceElement;
+ }
+ return null;
+ }
+
+ private static
void changeType(SourceFolder root, @NotNull JpsModuleSourceRootPropertiesSerializer
serializer, @Nullable Element serializedProps) {
+ root.changeType(
+ serializer.getType(),
+ serializedProps != null ? serializer.loadProperties(serializedProps) : serializer.getType().createDefaultProperties()
+ );
+ }
+
+ @Override
+ public int getModificationStamp() {
+ return myModificationStamp.get();
+ }
+
@NotNull
@Override
public Collection loadExtensions(@NotNull Class extensionClass) {
- String resourceName = "META-INF/services/" + extensionClass.getName();
- Set> classes = new LinkedHashSet<>();
Set loaders = new LinkedHashSet<>();
for (PluginDescriptor plugin : myExternalBuildPlugins) {
ContainerUtil.addIfNotNull(loaders, plugin.getPluginClassLoader());
@@ -56,7 +237,16 @@ public final class JpsIdePluginManagerImpl extends JpsPluginManager {
if (loaders.isEmpty()) {
loaders.add(getClass().getClassLoader());
}
+ return loadExtensionsFrom(loaders, extensionClass);
+ }
+ @NotNull
+ private static Collection loadExtensionsFrom(@NotNull Collection loaders, @NotNull Class extensionClass) {
+ if (loaders.isEmpty()) {
+ return Collections.emptyList();
+ }
+ String resourceName = "META-INF/services/" + extensionClass.getName();
+ Set> classes = new LinkedHashSet<>();
Set loadedUrls = new HashSet<>();
for (ClassLoader loader : loaders) {
try {
diff --git a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml
index 1423a722f67a..846cd713b05a 100644
--- a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml
+++ b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml
@@ -12,7 +12,7 @@
+ beanClass="com.intellij.jps.impl.JpsPluginBean" dynamic="true"/>
task) {
+ modifyModel(module, model -> {
+ task.consume(model);
+ return Boolean.TRUE;
+ });
+ }
+
+ public static void modifyModel(@NotNull Module module, @NotNull Function super ModifiableRootModel, Boolean> modifier) {
ModifiableRootModel model = ReadAction.compute(() -> ModuleRootManager.getInstance(module).getModifiableModel());
try {
- task.consume(model);
-
- ApplicationManager.getApplication().invokeAndWait(() -> {
- if (module.isDisposed()) return;
- WriteAction.run(model::commit);
- });
+ if (modifier.apply(model)) {
+ ApplicationManager.getApplication().invokeAndWait(() -> {
+ if (!module.isDisposed()) {
+ WriteAction.run(model::commit);
+ }
+ });
+ }
}
finally {
if (!model.isDisposed()) {
diff --git a/platform/projectModel-api/src/com/intellij/openapi/roots/SourceFolder.java b/platform/projectModel-api/src/com/intellij/openapi/roots/SourceFolder.java
index 8506f623bbdb..9d73f6d6b7dc 100644
--- a/platform/projectModel-api/src/com/intellij/openapi/roots/SourceFolder.java
+++ b/platform/projectModel-api/src/com/intellij/openapi/roots/SourceFolder.java
@@ -17,6 +17,7 @@ package com.intellij.openapi.roots;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsElement;
import org.jetbrains.jps.model.module.JpsModuleSourceRoot;
import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
@@ -55,4 +56,6 @@ public interface SourceFolder extends ContentFolder {
@NotNull
JpsModuleSourceRoot getJpsElement();
+
+ void changeType(JpsModuleSourceRootType
newType, P properties);
}
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/SourceFolderImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/SourceFolderImpl.java
index eda7df3e0c1b..da061fed2b67 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/SourceFolderImpl.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/SourceFolderImpl.java
@@ -14,7 +14,9 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.JpsElement;
import org.jetbrains.jps.model.JpsElementFactory;
-import org.jetbrains.jps.model.java.*;
+import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes;
+import org.jetbrains.jps.model.java.JavaResourceRootProperties;
+import org.jetbrains.jps.model.java.JavaSourceRootProperties;
import org.jetbrains.jps.model.module.JpsModuleSourceRoot;
import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
import org.jetbrains.jps.model.module.JpsTypedModuleSourceRoot;
@@ -25,7 +27,7 @@ import org.jetbrains.jps.model.serialization.module.JpsModuleRootModelSerializer
*/
@ApiStatus.Internal
public class SourceFolderImpl extends ContentFolderBaseImpl implements SourceFolder, ClonableContentFolder {
- private final JpsModuleSourceRoot myJpsElement;
+ private JpsModuleSourceRoot myJpsElement;
@NonNls public static final String ELEMENT_NAME = JpsModuleRootModelSerializer.SOURCE_FOLDER_TAG;
@NonNls public static final String TEST_SOURCE_ATTR = JpsModuleRootModelSerializer.IS_TEST_SOURCE_ATTRIBUTE;
static final String DEFAULT_PACKAGE_PREFIX = "";
@@ -112,6 +114,11 @@ public class SourceFolderImpl extends ContentFolderBaseImpl implements SourceFol
return myJpsElement;
}
+ @Override
+ public
void changeType(JpsModuleSourceRootType
newType, P properties) {
+ myJpsElement = JpsElementFactory.getInstance().createModuleSourceRoot(myJpsElement.getUrl(), newType, properties);
+ }
+
private boolean isForGeneratedSources() {
JavaSourceRootProperties properties = getJavaProperties();
JavaResourceRootProperties resourceJavaProperties = getResourceJavaProperties();
diff --git a/platform/projectModel-impl/src/com/intellij/project/model/impl/module/content/JpsSourceFolder.java b/platform/projectModel-impl/src/com/intellij/project/model/impl/module/content/JpsSourceFolder.java
index e25a8085eae6..328d83e74ff5 100644
--- a/platform/projectModel-impl/src/com/intellij/project/model/impl/module/content/JpsSourceFolder.java
+++ b/platform/projectModel-impl/src/com/intellij/project/model/impl/module/content/JpsSourceFolder.java
@@ -18,6 +18,8 @@ package com.intellij.project.model.impl.module.content;
import com.intellij.openapi.roots.SourceFolder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.JpsElementFactory;
import org.jetbrains.jps.model.JpsSimpleElement;
import org.jetbrains.jps.model.java.JavaSourceRootProperties;
import org.jetbrains.jps.model.java.JavaSourceRootType;
@@ -25,13 +27,15 @@ import org.jetbrains.jps.model.module.JpsModuleSourceRoot;
import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
public class JpsSourceFolder extends JpsContentFolderBase implements SourceFolder {
- private final JpsModuleSourceRoot mySourceRoot;
+ @NotNull
+ private JpsModuleSourceRoot mySourceRoot;
- public JpsSourceFolder(JpsModuleSourceRoot sourceRoot, JpsContentEntry contentEntry) {
+ public JpsSourceFolder(@NotNull JpsModuleSourceRoot sourceRoot, JpsContentEntry contentEntry) {
super(sourceRoot.getUrl(), contentEntry);
mySourceRoot = sourceRoot;
}
+ @NotNull
public JpsModuleSourceRoot getSourceRoot() {
return mySourceRoot;
}
@@ -78,4 +82,9 @@ public class JpsSourceFolder extends JpsContentFolderBase implements SourceFolde
public JpsModuleSourceRoot getJpsElement() {
return mySourceRoot;
}
+
+ @Override
+ public
void changeType(JpsModuleSourceRootType
newType, P properties) {
+ mySourceRoot = JpsElementFactory.getInstance().createModuleSourceRoot(mySourceRoot.getUrl(), newType, properties);
+ }
}
diff --git a/platform/workspaceModel-ide-tests/testSrc/com/intellij/workspace/jps/LegacyBridgeModuleLibraryTest.kt b/platform/workspaceModel-ide-tests/testSrc/com/intellij/workspace/jps/LegacyBridgeModuleLibraryTest.kt
index 71fb4d06bb79..0d78231cc415 100644
--- a/platform/workspaceModel-ide-tests/testSrc/com/intellij/workspace/jps/LegacyBridgeModuleLibraryTest.kt
+++ b/platform/workspaceModel-ide-tests/testSrc/com/intellij/workspace/jps/LegacyBridgeModuleLibraryTest.kt
@@ -171,7 +171,7 @@ class LegacyBridgeModuleLibraryTest {
StoreUtil.saveDocumentsAndProjectSettings(project)
val template = "\$MODULE_DIR\$"
- assertTrue(moduleFile.readText().contains("""
+ assertTrue(moduleFile.readText().replace("\r\n", "\n").contains("""
diff --git a/platform/workspaceModel-ide-tests/testSrc/com/intellij/workspace/jps/LegacyBridgeModulesTest.kt b/platform/workspaceModel-ide-tests/testSrc/com/intellij/workspace/jps/LegacyBridgeModulesTest.kt
index 387778b83e85..00a9e319ee9c 100644
--- a/platform/workspaceModel-ide-tests/testSrc/com/intellij/workspace/jps/LegacyBridgeModulesTest.kt
+++ b/platform/workspaceModel-ide-tests/testSrc/com/intellij/workspace/jps/LegacyBridgeModulesTest.kt
@@ -2,11 +2,13 @@ package com.intellij.workspace.jps
import com.intellij.configurationStore.StoreUtil
import com.intellij.openapi.application.ApplicationManager
-import com.intellij.openapi.application.WriteAction
import com.intellij.openapi.application.invokeAndWaitIfNeeded
import com.intellij.openapi.application.runWriteActionAndWait
import com.intellij.openapi.command.WriteCommandAction
-import com.intellij.openapi.module.*
+import com.intellij.openapi.module.EmptyModuleType
+import com.intellij.openapi.module.ModuleManager
+import com.intellij.openapi.module.ModuleType
+import com.intellij.openapi.module.ModuleTypeId
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ProjectManager
import com.intellij.openapi.project.ex.ProjectManagerEx
@@ -28,9 +30,9 @@ import com.intellij.workspace.api.*
import com.intellij.workspace.ide.*
import com.intellij.workspace.legacyBridge.intellij.LegacyBridgeModule
import com.intellij.workspace.toVirtualFileUrl
-import org.jetbrains.jps.model.java.JavaSourceRootProperties
-import org.jetbrains.jps.model.java.JavaSourceRootType
import org.jetbrains.jps.model.java.LanguageLevel
+import org.jetbrains.jps.model.module.UnknownSourceRootType
+import org.jetbrains.jps.model.module.UnknownSourceRootTypeProperties
import org.jetbrains.jps.model.serialization.JDomSerializationUtil
import org.jetbrains.jps.model.serialization.library.JpsLibraryTableSerializer
import org.junit.Assert.*
@@ -517,8 +519,8 @@ class LegacyBridgeModulesTest {
val contentEntry = ModuleRootManager.getInstance(module).contentEntries.single()
val sourceFolder = contentEntry.sourceFolders.single()
- assertSame(JavaSourceRootType.SOURCE, sourceFolder.rootType)
- assertTrue(sourceFolder.jpsElement.properties is JavaSourceRootProperties)
+ assertSame(UnknownSourceRootType.getInstance("unsupported-custom-source-root-type", false), sourceFolder.rootType)
+ assertTrue(sourceFolder.jpsElement.properties is UnknownSourceRootTypeProperties<*>)
val customRoot = WorkspaceModel.getInstance(project).entityStore.current.entities(CustomSourceRootPropertiesEntity::class.java)
.toList().single()
diff --git a/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/roots/LegacyBridgeModifiableContentEntryImpl.kt b/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/roots/LegacyBridgeModifiableContentEntryImpl.kt
index fe360eb909fe..aabce82d5087 100644
--- a/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/roots/LegacyBridgeModifiableContentEntryImpl.kt
+++ b/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/roots/LegacyBridgeModifiableContentEntryImpl.kt
@@ -23,9 +23,11 @@ import org.jetbrains.jps.model.java.JavaResourceRootProperties
import org.jetbrains.jps.model.java.JavaSourceRootProperties
import org.jetbrains.jps.model.java.JavaSourceRootType
import org.jetbrains.jps.model.module.JpsModuleSourceRootType
+import org.jetbrains.jps.model.module.UnknownSourceRootType
import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension
import org.jetbrains.jps.model.serialization.module.JpsModuleRootModelSerializer
import org.jetbrains.jps.model.serialization.module.JpsModuleSourceRootPropertiesSerializer
+import org.jetbrains.jps.model.serialization.module.UnknownSourceRootPropertiesSerializer
internal class LegacyBridgeModifiableContentEntryImpl(
private val diff: TypedEntityStorageDiffBuilder,
@@ -53,10 +55,12 @@ internal class LegacyBridgeModifiableContentEntryImpl(
}
@Suppress("UNCHECKED_CAST")
- val serializer: JpsModuleSourceRootPropertiesSerializer = (JpsModelSerializerExtension.getExtensions()
+ val serializer: JpsModuleSourceRootPropertiesSerializer
= if (type is UnknownSourceRootType)
+ UnknownSourceRootPropertiesSerializer.forType(type as UnknownSourceRootType) as JpsModuleSourceRootPropertiesSerializer
+ else
+ (JpsModelSerializerExtension.getExtensions()
.flatMap { it.moduleSourceRootPropertiesSerializers }
- .firstOrNull { it.type == type }) as? JpsModuleSourceRootPropertiesSerializer
- ?: error("Module source root type $type is not registered as JpsModelSerializerExtension")
+ .firstOrNull { it.type == type }) as? JpsModuleSourceRootPropertiesSerializer
?: error("Module source root type $type is not registered as JpsModelSerializerExtension")
val entitySource = currentContentEntry.value.entity.entitySource
val sourceRootEntity = diff.addSourceRootEntity(
diff --git a/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/typedModel/module/ContentFolderViaTypedEntity.kt b/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/typedModel/module/ContentFolderViaTypedEntity.kt
index e2b39595f4cb..ba4df923afb5 100644
--- a/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/typedModel/module/ContentFolderViaTypedEntity.kt
+++ b/platform/workspaceModel-ide/src/com/intellij/workspace/legacyBridge/typedModel/module/ContentFolderViaTypedEntity.kt
@@ -10,15 +10,16 @@ import com.intellij.workspace.api.*
import com.intellij.workspace.legacyBridge.intellij.LegacyBridgeFilePointerScope
import org.jetbrains.jps.model.JpsElement
import org.jetbrains.jps.model.JpsElementFactory
-import org.jetbrains.jps.model.java.JavaSourceRootType
import org.jetbrains.jps.model.java.JpsJavaExtensionService
import org.jetbrains.jps.model.module.JpsModuleSourceRoot
import org.jetbrains.jps.model.module.JpsModuleSourceRootType
+import org.jetbrains.jps.model.module.UnknownSourceRootType
import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension
import org.jetbrains.jps.model.serialization.java.JpsJavaModelSerializerExtension
import org.jetbrains.jps.model.serialization.module.JpsModuleRootModelSerializer
import org.jetbrains.jps.model.serialization.module.JpsModuleRootModelSerializer.SOURCE_ROOT_TYPE_ATTRIBUTE
import org.jetbrains.jps.model.serialization.module.JpsModuleRootModelSerializer.URL_ATTRIBUTE
+import org.jetbrains.jps.model.serialization.module.UnknownSourceRootPropertiesSerializer
internal abstract class ContentFolderViaTypedEntity(private val entry: ContentEntryViaTypedEntity, private val contentFolderUrl: VirtualFileUrl) : ContentFolder {
override fun getContentEntry(): ContentEntryViaTypedEntity = entry
@@ -34,7 +35,7 @@ internal class SourceFolderViaTypedEntity(private val entry: ContentEntryViaType
override fun getFile(): VirtualFile? = entry.model.filePointerProvider.getAndCacheFilePointer(sourceRootEntity.url, LegacyBridgeFilePointerScope.SourceRoot).file
private var packagePrefixVar: String? = null
- private val sourceRootType: JpsModuleSourceRootType<*> by lazy { getSourceRootType(sourceRootEntity.rootType) }
+ private var sourceRootType: JpsModuleSourceRootType = getSourceRootType(sourceRootEntity)
override fun getRootType() = sourceRootType
override fun isTestSource() = sourceRootEntity.tests
@@ -71,7 +72,10 @@ internal class SourceFolderViaTypedEntity(private val entry: ContentEntryViaType
val customSourceRoot = sourceRootEntity.asCustomSourceRoot() ?: return elementFactory.createDummyElement()
if (customSourceRoot.propertiesXmlTag.isEmpty()) return rootType.createDefaultProperties()
- val serializer = JpsModelSerializerExtension.getExtensions()
+ val serializer = if (rootType is UnknownSourceRootType)
+ UnknownSourceRootPropertiesSerializer.forType(rootType as UnknownSourceRootType)
+ else
+ JpsModelSerializerExtension.getExtensions ()
.flatMap { it.moduleSourceRootPropertiesSerializers }
.firstOrNull { it.type == rootType }
if (serializer == null) {
@@ -91,6 +95,10 @@ internal class SourceFolderViaTypedEntity(private val entry: ContentEntryViaType
}
}
+ override fun changeType(newType: JpsModuleSourceRootType
, properties: P) {
+ sourceRootType = newType
+ }
+
override fun hashCode() = entry.url.hashCode()
override fun equals(other: Any?): Boolean {
if (other !is SourceFolderViaTypedEntity) return false
@@ -142,13 +150,13 @@ internal class SourceFolderViaTypedEntity(private val entry: ContentEntryViaType
packagePrefixVar = packagePrefix
}
- private fun getSourceRootType(rootType: String): JpsModuleSourceRootType<*> {
+ private fun getSourceRootType(entity: SourceRootEntity): JpsModuleSourceRootType {
JpsModelSerializerExtension.getExtensions().forEach { extensions ->
extensions.moduleSourceRootPropertiesSerializers.forEach {
- if (it.typeId == rootType) return it.type
+ if (it.typeId == entity.rootType) return it.type
}
}
- return JavaSourceRootType.SOURCE
+ return UnknownSourceRootType.getInstance(entity.rootType, entity.tests)
}
companion object {