diff --git a/java/java-tests/testSrc/com/intellij/roots/ModuleRootsExternalizationTest.java b/java/java-tests/testSrc/com/intellij/roots/ModuleRootsExternalizationTest.java
index 63a2ea9db5ae..c9f9cc46bd7c 100644
--- a/java/java-tests/testSrc/com/intellij/roots/ModuleRootsExternalizationTest.java
+++ b/java/java-tests/testSrc/com/intellij/roots/ModuleRootsExternalizationTest.java
@@ -4,7 +4,6 @@ package com.intellij.roots;
import com.intellij.application.options.ReplacePathToMacroMap;
import com.intellij.configurationStore.StoreUtil;
import com.intellij.ide.highlighter.ModuleFileType;
-import com.intellij.jps.impl.JpsIdePluginManagerImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.ExpandMacroToPathMap;
import com.intellij.openapi.module.Module;
@@ -21,19 +20,16 @@ import com.intellij.testFramework.JavaModuleTestCase;
import com.intellij.testFramework.PsiTestUtil;
import org.jdom.Element;
import org.jdom.JDOMException;
-import org.jetbrains.jps.model.JpsElement;
-import org.jetbrains.jps.model.java.JavaSourceRootProperties;
-import org.jetbrains.jps.model.java.JavaSourceRootType;
-import org.jetbrains.jps.model.java.JpsJavaExtensionService;
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.JpsModuleSourceRootPropertiesSerializer;
import java.io.File;
import java.io.IOException;
-import java.util.*;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
import java.util.stream.Collectors;
import static com.intellij.testFramework.assertions.Assertions.assertThat;
@@ -151,70 +147,6 @@ public class ModuleRootsExternalizationTest extends JavaModuleTestCase {
);
}
- public void testChangeRootType() throws JDOMException, IOException {
- File content = new File(getProject().getBasePath());
- File source = new File(content, "source");
- File testSource = new File(content, "testSource");
- FileUtil.createDirectory(source);
- FileUtil.createDirectory(testSource);
- final VirtualFile contentFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(content);
- assertNotNull(contentFile);
- refreshRecursively(contentFile);
- final VirtualFile sourceFile = LocalFileSystem.getInstance().findFileByIoFile(source);
- assertNotNull(sourceFile);
- final VirtualFile testSourceFile = LocalFileSystem.getInstance().findFileByIoFile(testSource);
- assertNotNull(testSourceFile);
-
- final File moduleFile = new File(content, "test.iml");
- final Module module = createModule(moduleFile);
-
- PsiTestUtil.addContentRoot(module, contentFile);
- PsiTestUtil.addSourceRoot(
- module, sourceFile, JavaSourceRootType.SOURCE, JpsJavaExtensionService.getInstance().createSourceRootProperties("org.jetbrains", true)
- );
- PsiTestUtil.addSourceRoot(
- module, testSourceFile, JavaSourceRootType.TEST_SOURCE, JpsJavaExtensionService.getInstance().createSourceRootProperties("org.jetbrains", false)
- );
-
- StoreUtil.saveDocumentsAndProjectSettings(myProject);
-
- String expectedXml = "\n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- "";
-
- assertEquals(expectedXml, JDOMUtil.writeElement(JDOMUtil.load(moduleFile).getChild("component")));
-
- JpsIdePluginManagerImpl.replaceWithUnknownRootType(myProject, findSerializers(Arrays.asList(JavaSourceRootType.SOURCE, JavaSourceRootType.TEST_SOURCE)));
- for (ContentEntry entry : ModuleRootManager.getInstance(module).getContentEntries()) {
- for (SourceFolder folder : entry.getSourceFolders()) {
- assertTrue("Root type expected to be 'Unknown' for " + folder.getUrl(), folder.getRootType() instanceof UnknownSourceRootType);
- JpsElement properties = folder.getJpsElement().getProperties(folder.getRootType());
- assertTrue(properties instanceof UnknownSourceRootTypeProperties>);
- assertTrue(((UnknownSourceRootTypeProperties>)properties).getPropertiesData() instanceof Element);
- }
- }
- StoreUtil.saveSettings(myProject, true);
- assertEquals(expectedXml, JDOMUtil.writeElement(JDOMUtil.load(moduleFile).getChild("component")));
-
- JpsIdePluginManagerImpl.updateCustomRootTypes(myProject, findSerializers(Arrays.asList(JavaSourceRootType.SOURCE, JavaSourceRootType.TEST_SOURCE)));
- for (ContentEntry entry : ModuleRootManager.getInstance(module).getContentEntries()) {
- for (SourceFolder folder : entry.getSourceFolders()) {
- assertFalse("'Unknown' root type is not expected: " + folder.getUrl(), folder.getRootType() instanceof UnknownSourceRootType);
- JpsElement properties = folder.getJpsElement().getProperties(folder.getRootType());
- assertTrue(properties instanceof JavaSourceRootProperties);
- assertEquals("org.jetbrains", ((JavaSourceRootProperties)properties).getPackagePrefix());
- }
- }
- StoreUtil.saveSettings(myProject, true);
- assertEquals(expectedXml, JDOMUtil.writeElement(JDOMUtil.load(moduleFile).getChild("component")));
- }
-
-
private static Collection> findSerializers(Collection> rootTypes) {
final Set> typesSet = rootTypes instanceof Set ? (Set>)rootTypes : new HashSet<>(rootTypes);
Set> result = new HashSet<>();
diff --git a/platform/extensions/src/com/intellij/openapi/extensions/ExtensionPoint.java b/platform/extensions/src/com/intellij/openapi/extensions/ExtensionPoint.java
index 770f249ea072..48dc95ab3a04 100644
--- a/platform/extensions/src/com/intellij/openapi/extensions/ExtensionPoint.java
+++ b/platform/extensions/src/com/intellij/openapi/extensions/ExtensionPoint.java
@@ -35,6 +35,9 @@ public interface ExtensionPoint<@NotNull T> {
@TestOnly
void registerExtension(@NotNull T extension, @NotNull Disposable parentDisposable);
+ @TestOnly
+ void registerExtension(@NotNull T extension, @NotNull PluginDescriptor pluginDescriptor, @NotNull Disposable parentDisposable);
+
/**
* Use {@link com.intellij.testFramework.PlatformTestUtil#maskExtensions}
* to register extension as first or to completely replace existing extensions in tests.
diff --git a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java
index 76e663a7d9e8..b2f205f05b87 100644
--- a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java
+++ b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java
@@ -118,12 +118,18 @@ public abstract class ExtensionPointImpl<@NotNull T> implements ExtensionPoint implements ExtensionPoint implements ExtensionPoint adapter = new ObjectComponentAdapter<>(extension, getPluginDescriptor(), order);
+ ObjectComponentAdapter adapter = new ObjectComponentAdapter<>(extension, pluginDescriptor, order);
addExtensionAdapter(adapter);
notifyListeners(false, Collections.singletonList(adapter), myListeners);
diff --git a/platform/lang-impl/testSources/com/intellij/openapi/roots/CustomSourceRootTypeTest.kt b/platform/lang-impl/testSources/com/intellij/openapi/roots/CustomSourceRootTypeTest.kt
new file mode 100644
index 000000000000..4ab6a35e7ef6
--- /dev/null
+++ b/platform/lang-impl/testSources/com/intellij/openapi/roots/CustomSourceRootTypeTest.kt
@@ -0,0 +1,80 @@
+// 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 com.intellij.openapi.roots
+
+import com.intellij.openapi.module.Module
+import com.intellij.openapi.util.Disposer
+import com.intellij.testFramework.ApplicationRule
+import com.intellij.testFramework.DisposableRule
+import com.intellij.testFramework.rules.ProjectModelRule
+import com.intellij.testFramework.rules.TempDirectory
+import org.assertj.core.api.Assertions.assertThat
+import org.jetbrains.jps.model.module.UnknownSourceRootType
+import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension
+import org.junit.Before
+import org.junit.ClassRule
+import org.junit.Rule
+import org.junit.Test
+
+class CustomSourceRootTypeTest {
+ companion object {
+ @JvmField
+ @ClassRule
+ val appRule = ApplicationRule()
+ }
+
+ @Rule
+ @JvmField
+ val projectModel = ProjectModelRule()
+
+ @Rule
+ @JvmField
+ val tempDirectory = TempDirectory()
+
+ @Rule
+ @JvmField
+ val disposable = DisposableRule()
+
+ lateinit var module: Module
+
+ @Before
+ fun setUp() {
+ module = projectModel.createModule()
+ JpsModelSerializerExtension.getExtensions()
+ }
+
+ @Test
+ fun `load unload custom source root`() {
+ val srcDir = projectModel.baseProjectDir.newVirtualDirectory("src")
+ runWithRegisteredExtension {
+ val model = createModifiableModel(module)
+ model.addContentEntry(srcDir).addSourceFolder(srcDir, TestCustomSourceRootType.INSTANCE, TestCustomSourceRootProperties("hello"))
+ val committed = commitModifiableRootModel(model)
+ val sourceFolder = committed.contentEntries.single().sourceFolders.single()
+ assertThat(sourceFolder.file).isEqualTo(srcDir)
+ assertThat(sourceFolder.rootType).isEqualTo(TestCustomSourceRootType.INSTANCE)
+ assertThat((sourceFolder.jpsElement.properties as TestCustomSourceRootProperties).testString).isEqualTo("hello")
+ }
+
+ val sourceFolderWithUnknownType = ModuleRootManager.getInstance(module).contentEntries.single().sourceFolders.single()
+ assertThat(sourceFolderWithUnknownType.file).isEqualTo(srcDir)
+ assertThat(sourceFolderWithUnknownType.rootType).isInstanceOf(UnknownSourceRootType::class.java)
+
+ TestCustomRootModelSerializerExtension.registerTestCustomSourceRootType(tempDirectory.newDirectory(), disposable.disposable)
+ val sourceFolder = ModuleRootManager.getInstance(module).contentEntries.single().sourceFolders.single()
+ assertThat(sourceFolder.file).isEqualTo(srcDir)
+ assertThat(sourceFolder.rootType).isEqualTo(TestCustomSourceRootType.INSTANCE)
+ assertThat((sourceFolder.jpsElement.properties as TestCustomSourceRootProperties).testString).isEqualTo("hello")
+ }
+
+ private fun runWithRegisteredExtension(action: () -> Unit) {
+ val disposable = Disposer.newDisposable()
+ TestCustomRootModelSerializerExtension.registerTestCustomSourceRootType(tempDirectory.newDirectory(), disposable)
+ try {
+ action()
+ }
+ finally {
+ Disposer.dispose(disposable)
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/platform/workspaceModel-ide-tests/testSrc/com/intellij/workspace/jps/TestCustomSourceRoot.kt b/platform/lang-impl/testSources/com/intellij/openapi/roots/TestCustomSourceRoot.kt
similarity index 62%
rename from platform/workspaceModel-ide-tests/testSrc/com/intellij/workspace/jps/TestCustomSourceRoot.kt
rename to platform/lang-impl/testSources/com/intellij/openapi/roots/TestCustomSourceRoot.kt
index d0647d1bc7aa..d93bb7dc43a6 100644
--- a/platform/workspaceModel-ide-tests/testSrc/com/intellij/workspace/jps/TestCustomSourceRoot.kt
+++ b/platform/lang-impl/testSources/com/intellij/openapi/roots/TestCustomSourceRoot.kt
@@ -1,17 +1,45 @@
-// Copyright 2000-2019 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 com.intellij.workspace.jps
+// 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.
+@file:Suppress("unused")
-import com.intellij.openapi.util.JDOMUtil
+package com.intellij.openapi.roots
+
+import com.intellij.jps.impl.JpsPluginBean
+import com.intellij.openapi.Disposable
+import com.intellij.openapi.application.runWriteActionAndWait
+import com.intellij.openapi.extensions.DefaultPluginDescriptor
+import com.intellij.openapi.extensions.PluginId
+import com.intellij.openapi.util.Disposer
+import com.intellij.openapi.util.io.FileUtil
+import com.intellij.util.lang.UrlClassLoader
import org.jdom.Element
import org.jetbrains.jps.model.ex.JpsElementBase
import org.jetbrains.jps.model.ex.JpsElementTypeBase
import org.jetbrains.jps.model.module.JpsModuleSourceRootType
import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension
import org.jetbrains.jps.model.serialization.module.JpsModuleSourceRootPropertiesSerializer
+import java.io.File
class TestCustomRootModelSerializerExtension : JpsModelSerializerExtension() {
override fun getModuleSourceRootPropertiesSerializers(): List> =
listOf(TestCustomSourceRootPropertiesSerializer(TestCustomSourceRootType.INSTANCE, TestCustomSourceRootType.TYPE_ID))
+
+ companion object {
+ fun registerTestCustomSourceRootType(tempPluginRoot: File, disposable: Disposable) {
+ val jpsPluginDisposable = Disposer.newDisposable()
+ Disposer.register(disposable, Disposable {
+ runWriteActionAndWait {
+ Disposer.dispose(jpsPluginDisposable)
+ }
+ })
+
+ FileUtil.writeToFile(File(tempPluginRoot, "META-INF/services/${JpsModelSerializerExtension::class.java.name}"),
+ TestCustomRootModelSerializerExtension::class.java.name)
+ val pluginClassLoader = UrlClassLoader.build().parent(TestCustomRootModelSerializerExtension::class.java.classLoader).urls(tempPluginRoot.toURI().toURL()).get()
+ val pluginDescriptor = DefaultPluginDescriptor(PluginId.getId("com.intellij.custom.source.root.test"), pluginClassLoader)
+ JpsPluginBean.EP_NAME.point.registerExtension(JpsPluginBean(), pluginDescriptor, jpsPluginDisposable)
+ }
+
+ }
}
class TestCustomSourceRootType private constructor() : JpsElementTypeBase(), JpsModuleSourceRootType {
@@ -48,9 +76,6 @@ class TestCustomSourceRootPropertiesSerializer(
: JpsModuleSourceRootPropertiesSerializer(type, typeId) {
override fun loadProperties(sourceRootTag: Element): TestCustomSourceRootProperties {
- if (sourceRootTag.getAttributeValue("url") == null) error("url is missing in '${JDOMUtil.writeElement(sourceRootTag)}'")
- if (sourceRootTag.getAttributeValue("type") != typeId) error("expected type '$typeId' in '${JDOMUtil.writeElement(sourceRootTag)}'")
-
val testString = sourceRootTag.getAttributeValue("testString")
return TestCustomSourceRootProperties(testString)
}
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 9765ac75bf34..659fad9edb7a 100644
--- a/platform/platform-impl/src/com/intellij/jps/impl/JpsIdePluginManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/jps/impl/JpsIdePluginManagerImpl.java
@@ -145,7 +145,7 @@ public final class JpsIdePluginManagerImpl extends JpsPluginManager {
}
}
- public static void replaceWithUnknownRootType(Project project, Collection> unregisteredSerializers) {
+ private static void replaceWithUnknownRootType(Project project, Collection> unregisteredSerializers) {
if (unregisteredSerializers.isEmpty()) {
return;
}
@@ -174,7 +174,7 @@ public final class JpsIdePluginManagerImpl extends JpsPluginManager {
}
}
- public static void updateCustomRootTypes(Project project, Collection> registeredSerializers) {
+ private static void updateCustomRootTypes(Project project, Collection> registeredSerializers) {
if (registeredSerializers.isEmpty()) {
return;
}
diff --git a/platform/testFramework/src/com/intellij/testFramework/rules/ProjectModelRule.kt b/platform/testFramework/src/com/intellij/testFramework/rules/ProjectModelRule.kt
index aa959c9ee8cb..d6051deb9654 100644
--- a/platform/testFramework/src/com/intellij/testFramework/rules/ProjectModelRule.kt
+++ b/platform/testFramework/src/com/intellij/testFramework/rules/ProjectModelRule.kt
@@ -1,6 +1,7 @@
// 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 com.intellij.testFramework.rules
+import com.intellij.openapi.application.invokeAndWaitIfNeeded
import com.intellij.openapi.application.runReadAction
import com.intellij.openapi.application.runWriteActionAndWait
import com.intellij.openapi.module.EmptyModuleType
@@ -30,7 +31,12 @@ import java.io.File
class ProjectModelRule : TestRule {
val baseProjectDir = TempDirectory()
- private val projectDelegate = lazy { createHeavyProject(baseProjectDir.root.toPath()) }
+ private val projectDelegate = lazy { val project = createHeavyProject(baseProjectDir.root.toPath())
+ invokeAndWaitIfNeeded {
+ ProjectManagerEx.getInstanceEx().openTestProject(project)
+ }
+ project
+ }
private val disposableRule = DisposableRule()
val project by projectDelegate
private val closeProject = object : ExternalResource() {
@@ -50,8 +56,9 @@ class ProjectModelRule : TestRule {
fun createModule(name: String = "module"): Module {
val imlFile = File(baseProjectDir.root, "$name/$name.iml")
+ val manager = moduleManager
return runWriteActionAndWait {
- moduleManager.newModule(imlFile.systemIndependentPath, EmptyModuleType.EMPTY_MODULE)
+ manager.newModule(imlFile.systemIndependentPath, EmptyModuleType.EMPTY_MODULE)
}
}
diff --git a/platform/workspaceModel-ide-tests/intellij.platform.workspaceModel.ide.tests.iml b/platform/workspaceModel-ide-tests/intellij.platform.workspaceModel.ide.tests.iml
index 317670601397..7671295d7c85 100644
--- a/platform/workspaceModel-ide-tests/intellij.platform.workspaceModel.ide.tests.iml
+++ b/platform/workspaceModel-ide-tests/intellij.platform.workspaceModel.ide.tests.iml
@@ -13,6 +13,7 @@
+
\ No newline at end of file
diff --git a/platform/workspaceModel-ide-tests/testResources/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelSerializerExtension b/platform/workspaceModel-ide-tests/testResources/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelSerializerExtension
deleted file mode 100644
index b9ea079670d7..000000000000
--- a/platform/workspaceModel-ide-tests/testResources/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelSerializerExtension
+++ /dev/null
@@ -1 +0,0 @@
-com.intellij.workspace.jps.TestCustomRootModelSerializerExtension
\ No newline at end of file
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 20c93e3eeffb..0ad4f4f69eaf 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
@@ -456,6 +456,8 @@ class LegacyBridgeModulesTest {
@Test
fun `test custom source root loading`() {
+ TestCustomRootModelSerializerExtension.registerTestCustomSourceRootType(temporaryDirectoryRule.newPath().toFile(),
+ disposableRule.disposable)
val tempDir = temporaryDirectoryRule.newPath().toFile()
val moduleImlFile = File(tempDir, "my.iml")
Files.createDirectories(moduleImlFile.parentFile.toPath())
@@ -534,6 +536,7 @@ class LegacyBridgeModulesTest {
@Test
fun `test custom source root saving`() {
val tempDir = temporaryDirectoryRule.newPath().toFile()
+ TestCustomRootModelSerializerExtension.registerTestCustomSourceRootType(temporaryDirectoryRule.newPath().toFile(), disposableRule.disposable)
val moduleImlFile = File(tempDir, "my.iml")
Files.createDirectories(moduleImlFile.parentFile.toPath())
@@ -581,17 +584,17 @@ class LegacyBridgeModulesTest {
val tempDir = temporaryDirectoryRule.newPath().toFile()
val url = VfsUtilCore.pathToUrl(FileUtil.toSystemIndependentName(tempDir.path))
val contentEntry = model.addContentEntry(url)
- contentEntry.addSourceFolder("$url/$antLibraryFolder", TestCustomSourceRootType.INSTANCE)
+ contentEntry.addSourceFolder("$url/$antLibraryFolder", false)
}
StoreUtil.saveDocumentsAndProjectSettings(project)
assertTrue(moduleFile.readText().contains(antLibraryFolder))
val entityStore = WorkspaceModel.getInstance(project).entityStore
assertEquals(1, entityStore.current.entities(ContentRootEntity::class.java).count())
- assertEquals(1, entityStore.current.entities(CustomSourceRootPropertiesEntity::class.java).count())
+ assertEquals(1, entityStore.current.entities(JavaSourceRootEntity::class.java).count())
ModuleManager.getInstance(project).disposeModule(module)
assertEmpty(entityStore.current.entities(ContentRootEntity::class.java).toList())
- assertEmpty(entityStore.current.entities(CustomSourceRootPropertiesEntity::class.java).toList())
+ assertEmpty(entityStore.current.entities(JavaSourceRootEntity::class.java).toList())
}
@Test
@@ -610,7 +613,7 @@ class LegacyBridgeModulesTest {
val tempDir = temporaryDirectoryRule.newPath().toFile()
val url = VfsUtilCore.pathToUrl(FileUtil.toSystemIndependentName(tempDir.path))
val contentEntry = model.addContentEntry(url)
- contentEntry.addSourceFolder("$url/$antLibraryFolder", TestCustomSourceRootType.INSTANCE)
+ contentEntry.addSourceFolder("$url/$antLibraryFolder", false)
}
val entityStore = WorkspaceModel.getInstance(project).entityStore