mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-16 14:23:28 +07:00
IJPL-185294 [refactoring] Move loadExtensionWithText to intellij.platform.testFramework
GitOrigin-RevId: fd41e2f70858313b1b56a7aae6e2e4fed995c9f7
This commit is contained in:
committed by
intellij-monorepo-bot
parent
48f8d29dd0
commit
32a5548e23
@@ -6,10 +6,10 @@ import com.intellij.facet.FacetManager;
|
||||
import com.intellij.facet.mock.*;
|
||||
import com.intellij.framework.detection.impl.FacetBasedDetectedFrameworkDescription;
|
||||
import com.intellij.framework.detection.impl.FrameworkDetectionManager;
|
||||
import com.intellij.ide.plugins.DynamicPluginsTestUtil;
|
||||
import com.intellij.openapi.application.WriteAction;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.platform.testFramework.DynamicPluginTestUtilsKt;
|
||||
import com.intellij.testFramework.PsiTestUtil;
|
||||
import com.intellij.testFramework.VfsTestUtil;
|
||||
|
||||
@@ -52,7 +52,7 @@ public class FrameworkDetectionTest extends FrameworkDetectionTestCase {
|
||||
VirtualFile file = createFrameworkConfig("my-config.xml");
|
||||
assertNoFrameworksDetected();
|
||||
|
||||
Disposer.register(getTestRootDisposable(), DynamicPluginsTestUtil.loadExtensionWithText(
|
||||
Disposer.register(getTestRootDisposable(), DynamicPluginTestUtilsKt.loadExtensionWithText(
|
||||
"<framework.detector implementation=\"" + MockFacetDetector.class.getName() + "\"/>",
|
||||
"com.intellij"));
|
||||
|
||||
|
||||
@@ -6,10 +6,10 @@ import com.intellij.facet.mock.MockFacetDetector;
|
||||
import com.intellij.facet.mock.MockSubFacetDetector;
|
||||
import com.intellij.framework.detection.impl.FrameworkDetectionManager;
|
||||
import com.intellij.framework.detection.impl.FrameworkDetectionUtil;
|
||||
import com.intellij.ide.plugins.DynamicPluginsTestUtil;
|
||||
import com.intellij.openapi.roots.PlatformModifiableModelsProvider;
|
||||
import com.intellij.openapi.roots.ui.configuration.DefaultModulesProvider;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.platform.testFramework.DynamicPluginTestUtilsKt;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -19,11 +19,11 @@ public abstract class FrameworkDetectionTestCase extends FacetTestCase {
|
||||
super.setUp();
|
||||
if (!"dynamicDetector".equals(getTestName(true))) {
|
||||
//todo we can get rid of this ugly check by converting facet tests to JUnit4 and using test rules to enable facet detection
|
||||
Disposer.register(getTestRootDisposable(), DynamicPluginsTestUtil.loadExtensionWithText(
|
||||
Disposer.register(getTestRootDisposable(), DynamicPluginTestUtilsKt.loadExtensionWithText(
|
||||
"<framework.detector implementation=\"" + MockFacetDetector.class.getName() + "\"/>",
|
||||
"com.intellij"));
|
||||
|
||||
Disposer.register(getTestRootDisposable(), DynamicPluginsTestUtil.loadExtensionWithText(
|
||||
Disposer.register(getTestRootDisposable(), DynamicPluginTestUtilsKt.loadExtensionWithText(
|
||||
"<framework.detector implementation=\"" + MockSubFacetDetector.class.getName() + "\"/>",
|
||||
"com.intellij"));
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.java.index.propertyBased
|
||||
|
||||
import com.intellij.ide.plugins.loadExtensionWithText
|
||||
import com.intellij.platform.testFramework.loadExtensionWithText
|
||||
import com.intellij.openapi.extensions.InternalIgnoreDependencyViolation
|
||||
import com.intellij.openapi.fileTypes.FileType
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.lang
|
||||
|
||||
import com.intellij.ide.plugins.loadExtensionWithText
|
||||
import com.intellij.platform.testFramework.loadExtensionWithText
|
||||
import com.intellij.lang.java.JavaLanguage
|
||||
import com.intellij.openapi.fileTypes.PlainTextLanguage
|
||||
import com.intellij.openapi.project.Project
|
||||
|
||||
@@ -5,13 +5,13 @@ import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInsight.daemon.LineMarkerInfo;
|
||||
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl;
|
||||
import com.intellij.codeInsight.daemon.impl.MarkerType;
|
||||
import com.intellij.ide.plugins.DynamicPluginsTestUtil;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.extensions.InternalIgnoreDependencyViolation;
|
||||
import com.intellij.openapi.roots.OrderRootType;
|
||||
import com.intellij.openapi.roots.impl.LibraryScopeCache;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.platform.testFramework.DynamicPluginTestUtilsKt;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
@@ -43,7 +43,7 @@ public class LibraryUseSearchUsingScopeEnlargerTest extends JavaCodeInsightFixtu
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
Disposer.register(getTestRootDisposable(), DynamicPluginsTestUtil.loadExtensionWithText(
|
||||
Disposer.register(getTestRootDisposable(), DynamicPluginTestUtilsKt.loadExtensionWithText(
|
||||
"<useScopeEnlarger implementation=\"com.intellij.scopes.LibraryUseSearchUsingScopeEnlargerTest$LibraryUseScopeEnlarger\"/>",
|
||||
"com.intellij"));
|
||||
//bug? Test seems to use stale data.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.util.indexing
|
||||
|
||||
import com.intellij.ide.plugins.loadExtensionWithText
|
||||
import com.intellij.platform.testFramework.loadExtensionWithText
|
||||
import com.intellij.openapi.extensions.InternalIgnoreDependencyViolation
|
||||
import com.intellij.openapi.fileTypes.FileType
|
||||
import com.intellij.openapi.fileTypes.FileTypeRegistry
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.util.indexing
|
||||
|
||||
import com.intellij.ide.plugins.loadExtensionWithText
|
||||
import com.intellij.platform.testFramework.loadExtensionWithText
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.extensions.InternalIgnoreDependencyViolation
|
||||
import com.intellij.openapi.util.Disposer
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.util.indexing
|
||||
|
||||
import com.intellij.ide.plugins.loadExtensionWithText
|
||||
import com.intellij.platform.testFramework.loadExtensionWithText
|
||||
import com.intellij.openapi.application.PathManager
|
||||
import com.intellij.openapi.extensions.InternalIgnoreDependencyViolation
|
||||
import com.intellij.openapi.project.Project
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package com.intellij.util.indexing
|
||||
|
||||
import com.intellij.find.ngrams.TrigramIndex
|
||||
import com.intellij.ide.plugins.loadExtensionWithText
|
||||
import com.intellij.platform.testFramework.loadExtensionWithText
|
||||
import com.intellij.openapi.extensions.InternalIgnoreDependencyViolation
|
||||
import com.intellij.openapi.module.JavaModuleType
|
||||
import com.intellij.openapi.project.DumbService
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.util.indexing
|
||||
|
||||
import com.intellij.ide.plugins.loadExtensionWithText
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.extensions.InternalIgnoreDependencyViolation
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.platform.testFramework.loadExtensionWithText
|
||||
import com.intellij.util.io.EnumeratorStringDescriptor
|
||||
import com.intellij.util.io.KeyDescriptor
|
||||
import com.intellij.util.io.VoidDataExternalizer
|
||||
|
||||
@@ -62,6 +62,5 @@
|
||||
<orderEntry type="module" module-name="intellij.platform.eel.provider" scope="TEST" />
|
||||
<orderEntry type="module" module-name="intellij.platform.statistics.testFramework" scope="TEST" />
|
||||
<orderEntry type="module" module-name="intellij.platform.testFramework.junit5.projectStructure" scope="TEST" />
|
||||
<orderEntry type="module" module-name="intellij.platform.tests" scope="TEST" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -4,7 +4,7 @@ package com.intellij.util.indexing
|
||||
import com.intellij.find.TextSearchService
|
||||
import com.intellij.ide.impl.ProjectUtil
|
||||
import com.intellij.ide.plugins.PluginManagerCore
|
||||
import com.intellij.ide.plugins.loadExtensionWithText
|
||||
import com.intellij.platform.testFramework.loadExtensionWithText
|
||||
import com.intellij.openapi.application.*
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.fileTypes.ExtensionFileNameMatcher
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.intellij.ide.plugins.cl.PluginClassLoader
|
||||
import com.intellij.openapi.util.BuildNumber
|
||||
import com.intellij.platform.ide.bootstrap.ZipFilePoolImpl
|
||||
import com.intellij.platform.plugins.parser.impl.PluginDescriptorBuilder
|
||||
import com.intellij.platform.testFramework.PluginBuilder
|
||||
import com.intellij.testFramework.assertions.Assertions.assertThat
|
||||
import com.intellij.testFramework.rules.InMemoryFsExtension
|
||||
import com.intellij.util.io.directoryStreamIfExists
|
||||
|
||||
@@ -40,6 +40,11 @@ import com.intellij.openapi.startup.StartupActivity
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.openapi.util.use
|
||||
import com.intellij.platform.testFramework.PluginBuilder
|
||||
import com.intellij.platform.testFramework.loadAndInitDescriptorInTest
|
||||
import com.intellij.platform.testFramework.loadExtensionWithText
|
||||
import com.intellij.platform.testFramework.setPluginClassLoaderForMainAndSubPlugins
|
||||
import com.intellij.platform.testFramework.unloadAndUninstallPlugin
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.testFramework.EdtRule
|
||||
import com.intellij.testFramework.ProjectRule
|
||||
@@ -86,7 +91,7 @@ class DynamicPluginsTest {
|
||||
pluginBuilder: PluginBuilder,
|
||||
disabledPlugins: Set<String> = emptySet(),
|
||||
): Disposable {
|
||||
return loadPluginWithText(
|
||||
return com.intellij.platform.testFramework.loadPluginWithText(
|
||||
pluginBuilder = pluginBuilder,
|
||||
path = rootPath.resolve(Ksuid.generate()),
|
||||
disabledPlugins = disabledPlugins,
|
||||
@@ -811,7 +816,8 @@ class DynamicPluginsTest {
|
||||
|
||||
private fun loadPluginWithOptionalDependency(pluginDescriptor: PluginBuilder,
|
||||
optionalDependencyDescriptor: PluginBuilder,
|
||||
dependsOn: PluginBuilder): Disposable {
|
||||
dependsOn: PluginBuilder
|
||||
): Disposable {
|
||||
pluginDescriptor.depends(dependsOn.id, optionalDependencyDescriptor)
|
||||
return loadPluginWithText(pluginDescriptor)
|
||||
}
|
||||
|
||||
@@ -1,27 +1,16 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.ide.plugins
|
||||
|
||||
import com.intellij.openapi.extensions.PluginId
|
||||
import com.intellij.platform.plugins.parser.impl.PluginDescriptorBuilder
|
||||
import com.intellij.platform.plugins.parser.impl.PluginDescriptorFromXmlStreamConsumer
|
||||
import com.intellij.platform.plugins.parser.impl.PluginXmlConst
|
||||
import com.intellij.platform.plugins.parser.impl.ReadModuleContext
|
||||
import com.intellij.platform.plugins.parser.impl.consume
|
||||
import com.intellij.platform.plugins.parser.impl.elements.OS
|
||||
import com.intellij.util.io.Compressor
|
||||
import com.intellij.util.io.createParentDirectories
|
||||
import com.intellij.util.io.write
|
||||
import com.intellij.util.xml.dom.NoOpXmlInterner
|
||||
import org.intellij.lang.annotations.Language
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.OutputStream
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import kotlin.io.path.createDirectories
|
||||
|
||||
private val pluginIdCounter = AtomicInteger()
|
||||
|
||||
fun plugin(outDir: Path, @Language("XML") descriptor: String) {
|
||||
val rawDescriptor = try {
|
||||
@@ -53,306 +42,6 @@ fun module(outDir: Path, ownerId: String, moduleId: String, @Language("XML") des
|
||||
outDir.resolve("$ownerId/$moduleId.xml").write(descriptor.trimIndent())
|
||||
}
|
||||
|
||||
class PluginBuilder private constructor() {
|
||||
private data class ExtensionBlock(val ns: String, val text: String)
|
||||
private data class DependsTag(val pluginId: String, val configFile: String?)
|
||||
|
||||
// counter is used to reduce plugin id length
|
||||
var id: String = "p_${pluginIdCounter.incrementAndGet()}"
|
||||
private set
|
||||
|
||||
private var implementationDetail = false
|
||||
private var separateJar = false
|
||||
private var name: String? = null
|
||||
private var description: String? = null
|
||||
private var packagePrefix: String? = null
|
||||
private val dependsTags = mutableListOf<DependsTag>()
|
||||
private var applicationListeners: String? = null
|
||||
private var resourceBundleBaseName: String? = null
|
||||
private var actions: String? = null
|
||||
private val extensions = mutableListOf<ExtensionBlock>()
|
||||
private var extensionPoints: String? = null
|
||||
private var untilBuild: String? = null
|
||||
private var sinceBuild: String? = null
|
||||
private var version: String? = null
|
||||
private val pluginAliases = mutableListOf<String>()
|
||||
|
||||
private val content = mutableListOf<PluginContentDescriptor.ModuleItem>()
|
||||
private val dependencies = mutableListOf<ModuleDependencies.ModuleReference>()
|
||||
private val pluginDependencies = mutableListOf<ModuleDependencies.PluginReference>()
|
||||
private val incompatibleWith = mutableListOf<ModuleDependencies.PluginReference>()
|
||||
|
||||
private data class SubDescriptor(val filename: String, val builder: PluginBuilder)
|
||||
private val subDescriptors = ArrayList<SubDescriptor>()
|
||||
|
||||
fun dependsIntellijModulesLang(): PluginBuilder {
|
||||
depends("com.intellij.modules.lang")
|
||||
return this
|
||||
}
|
||||
|
||||
fun id(id: String): PluginBuilder {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
fun randomId(idPrefix: String): PluginBuilder {
|
||||
this.id = "${idPrefix}_${pluginIdCounter.incrementAndGet()}"
|
||||
return this
|
||||
}
|
||||
|
||||
fun name(name: String): PluginBuilder {
|
||||
this.name = name
|
||||
return this
|
||||
}
|
||||
|
||||
fun description(description: String): PluginBuilder {
|
||||
this.description = description
|
||||
return this
|
||||
}
|
||||
|
||||
fun packagePrefix(value: String?): PluginBuilder {
|
||||
packagePrefix = value
|
||||
return this
|
||||
}
|
||||
|
||||
fun separateJar(value: Boolean): PluginBuilder {
|
||||
separateJar = value
|
||||
return this
|
||||
}
|
||||
|
||||
fun depends(pluginId: String, configFile: String? = null): PluginBuilder {
|
||||
dependsTags.add(DependsTag(pluginId, configFile))
|
||||
return this
|
||||
}
|
||||
|
||||
fun depends(pluginId: String, subDescriptor: PluginBuilder, filename: String? = null): PluginBuilder {
|
||||
val fileName = filename ?: "dep_${pluginIdCounter.incrementAndGet()}.xml"
|
||||
subDescriptors.add(SubDescriptor(PluginManagerCore.META_INF + fileName, subDescriptor))
|
||||
depends(pluginId, fileName)
|
||||
return this
|
||||
}
|
||||
|
||||
fun module(moduleName: String, moduleDescriptor: PluginBuilder, loadingRule: ModuleLoadingRule = ModuleLoadingRule.OPTIONAL,
|
||||
moduleFile: String = "$moduleName.xml"): PluginBuilder {
|
||||
subDescriptors.add(SubDescriptor(moduleFile, moduleDescriptor))
|
||||
content.add(PluginContentDescriptor.ModuleItem(name = moduleName, configFile = null, descriptorContent = null, loadingRule = loadingRule))
|
||||
return this
|
||||
}
|
||||
|
||||
fun pluginAlias(alias: String): PluginBuilder {
|
||||
pluginAliases.add(alias)
|
||||
return this
|
||||
}
|
||||
|
||||
fun dependency(moduleName: String): PluginBuilder {
|
||||
dependencies.add(ModuleDependencies.ModuleReference(moduleName))
|
||||
return this
|
||||
}
|
||||
|
||||
fun pluginDependency(pluginId: String): PluginBuilder {
|
||||
pluginDependencies.add(ModuleDependencies.PluginReference(PluginId.getId(pluginId)))
|
||||
return this
|
||||
}
|
||||
|
||||
fun incompatibleWith(pluginId: String): PluginBuilder {
|
||||
incompatibleWith.add(ModuleDependencies.PluginReference(PluginId.getId(pluginId)))
|
||||
return this
|
||||
}
|
||||
|
||||
fun resourceBundle(resourceBundle: String?): PluginBuilder {
|
||||
resourceBundleBaseName = resourceBundle
|
||||
return this
|
||||
}
|
||||
|
||||
fun untilBuild(buildNumber: String): PluginBuilder {
|
||||
untilBuild = buildNumber
|
||||
return this
|
||||
}
|
||||
|
||||
fun sinceBuild(buildNumber: String): PluginBuilder {
|
||||
sinceBuild = buildNumber
|
||||
return this
|
||||
}
|
||||
|
||||
fun version(version: String): PluginBuilder {
|
||||
this.version = version
|
||||
return this
|
||||
}
|
||||
|
||||
fun applicationListeners(text: String): PluginBuilder {
|
||||
applicationListeners = text
|
||||
return this
|
||||
}
|
||||
|
||||
fun actions(text: String): PluginBuilder {
|
||||
actions = text
|
||||
return this
|
||||
}
|
||||
|
||||
fun extensions(text: String, ns: String = "com.intellij"): PluginBuilder {
|
||||
extensions.add(ExtensionBlock(ns, text))
|
||||
return this
|
||||
}
|
||||
|
||||
fun extensionPoints(@Language("XML") text: String): PluginBuilder {
|
||||
extensionPoints = text
|
||||
return this
|
||||
}
|
||||
|
||||
fun implementationDetail(): PluginBuilder {
|
||||
implementationDetail = true
|
||||
return this
|
||||
}
|
||||
|
||||
fun text(requireId: Boolean = true): String {
|
||||
return buildString {
|
||||
append("<idea-plugin")
|
||||
if (implementationDetail) {
|
||||
append(""" ${PluginXmlConst.PLUGIN_IMPLEMENTATION_DETAIL_ATTR}="true"""")
|
||||
}
|
||||
packagePrefix?.let {
|
||||
append(""" ${PluginXmlConst.PLUGIN_PACKAGE_ATTR}="$it"""")
|
||||
}
|
||||
if (separateJar) {
|
||||
append(""" separate-jar="true"""") // todo change to const from xml reader
|
||||
}
|
||||
append(">")
|
||||
if (requireId) {
|
||||
append("<id>$id</id>")
|
||||
}
|
||||
name?.let { append("<name>$it</name>") }
|
||||
description?.let { append("<description>$it</description>") }
|
||||
for (dependsTag in dependsTags) {
|
||||
val configFile = dependsTag.configFile
|
||||
if (configFile != null) {
|
||||
append("""<depends optional="true" config-file="$configFile">${dependsTag.pluginId}</depends>""")
|
||||
}
|
||||
else {
|
||||
append("<depends>${dependsTag.pluginId}</depends>")
|
||||
}
|
||||
}
|
||||
version?.let { append("<version>$it</version>") }
|
||||
|
||||
if (sinceBuild != null && untilBuild != null) {
|
||||
append("""<idea-version since-build="${sinceBuild}" until-build="${untilBuild}"/>""")
|
||||
}
|
||||
else if (sinceBuild != null) {
|
||||
append("""<idea-version since-build="${sinceBuild}"/>""")
|
||||
}
|
||||
else if (untilBuild != null) {
|
||||
append("""<idea-version until-build="${untilBuild}"/>""")
|
||||
}
|
||||
|
||||
for (extensionBlock in extensions) {
|
||||
append("""<extensions defaultExtensionNs="${extensionBlock.ns}">${extensionBlock.text}</extensions>""")
|
||||
}
|
||||
extensionPoints?.let { append("<extensionPoints>$it</extensionPoints>") }
|
||||
applicationListeners?.let { append("<applicationListeners>$it</applicationListeners>") }
|
||||
resourceBundleBaseName?.let { append("""<resource-bundle>$it</resource-bundle>""") }
|
||||
actions?.let { append("<actions>$it</actions>") }
|
||||
|
||||
if (content.isNotEmpty()) {
|
||||
append("\n<content>\n ")
|
||||
content.joinTo(this, separator = "\n ") { moduleItem ->
|
||||
val loadingAttribute = when (moduleItem.loadingRule) {
|
||||
ModuleLoadingRule.OPTIONAL -> ""
|
||||
ModuleLoadingRule.REQUIRED -> "loading=\"required\" "
|
||||
ModuleLoadingRule.EMBEDDED -> "loading=\"embedded\" "
|
||||
ModuleLoadingRule.ON_DEMAND -> "loading=\"on-demand\" "
|
||||
}
|
||||
"""<module name="${moduleItem.name}" $loadingAttribute/>"""
|
||||
}
|
||||
append("\n</content>")
|
||||
}
|
||||
|
||||
if (incompatibleWith.isNotEmpty()) {
|
||||
incompatibleWith.joinTo(this, separator = "\n ") {
|
||||
"""<incompatible-with>${it.id}</incompatible-with>"""
|
||||
}
|
||||
}
|
||||
|
||||
if (dependencies.isNotEmpty() || pluginDependencies.isNotEmpty()) {
|
||||
append("\n<dependencies>\n ")
|
||||
if (dependencies.isNotEmpty()) {
|
||||
dependencies.joinTo(this, separator = "\n ") { """<module name="${it.name}" />""" }
|
||||
}
|
||||
if (pluginDependencies.isNotEmpty()) {
|
||||
pluginDependencies.joinTo(this, separator = "\n ") { """<plugin id="${it.id}" />""" }
|
||||
}
|
||||
append("\n</dependencies>")
|
||||
}
|
||||
|
||||
for (alias in pluginAliases) {
|
||||
append("\n")
|
||||
append("""<module value="$alias"/>""")
|
||||
}
|
||||
|
||||
append("</idea-plugin>")
|
||||
}
|
||||
}
|
||||
|
||||
fun build(path: Path): PluginBuilder {
|
||||
val allDescriptors = collectAllSubDescriptors(subDescriptors).toList()
|
||||
if (allDescriptors.any { it.builder.separateJar }) {
|
||||
val modulesDir = path.resolve("lib/modules")
|
||||
modulesDir.createDirectories()
|
||||
buildJar(path.resolve("lib/$id.jar"))
|
||||
for ((fileName, subDescriptor) in allDescriptors) {
|
||||
if (subDescriptor.separateJar) {
|
||||
val jarPath = modulesDir.resolve("${fileName.removeSuffix(".xml")}.jar")
|
||||
subDescriptor.buildJarToStream(Files.newOutputStream(jarPath), mainDescriptorRelativePath = fileName)
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
path.resolve(PluginManagerCore.PLUGIN_XML_PATH).write(text())
|
||||
for (subDescriptor in allDescriptors) {
|
||||
path.resolve(subDescriptor.filename).createParentDirectories().write(subDescriptor.builder.text(requireId = false))
|
||||
}
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
private fun collectAllSubDescriptors(descriptors: List<SubDescriptor>): Sequence<SubDescriptor> {
|
||||
return descriptors.asSequence().flatMap { sequenceOf(it) + collectAllSubDescriptors(it.builder.subDescriptors) }
|
||||
}
|
||||
|
||||
fun buildJar(path: Path): PluginBuilder {
|
||||
buildJarToStream(Files.newOutputStream(path), PluginManagerCore.PLUGIN_XML_PATH)
|
||||
return this
|
||||
}
|
||||
|
||||
private fun buildJarToStream(outputStream: OutputStream, mainDescriptorRelativePath: String) {
|
||||
Compressor.Zip(outputStream).use {
|
||||
it.addFile(mainDescriptorRelativePath, text(requireId = mainDescriptorRelativePath == PluginManagerCore.PLUGIN_XML_PATH).toByteArray())
|
||||
for ((fileName, subDescriptor) in subDescriptors) {
|
||||
if (!subDescriptor.separateJar) {
|
||||
it.addFile(fileName, subDescriptor.text(requireId = false).toByteArray())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun buildZip(path: Path): PluginBuilder {
|
||||
val jarStream = ByteArrayOutputStream()
|
||||
buildJarToStream(jarStream, PluginManagerCore.PLUGIN_XML_PATH)
|
||||
|
||||
val pluginName = name ?: id
|
||||
Compressor.Zip(Files.newOutputStream(path)).use {
|
||||
it.addDirectory(pluginName)
|
||||
it.addDirectory("$pluginName/lib")
|
||||
it.addFile("$pluginName/lib/$pluginName.jar", jarStream.toByteArray())
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun withModulesLang(): PluginBuilder = PluginBuilder().dependsIntellijModulesLang()
|
||||
fun empty(): PluginBuilder = PluginBuilder()
|
||||
}
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
fun readModuleDescriptorForTest(input: ByteArray): PluginDescriptorBuilder {
|
||||
return PluginDescriptorFromXmlStreamConsumer(readContext = object : ReadModuleContext {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
package com.intellij.ide.plugins
|
||||
|
||||
import com.intellij.ide.plugins.cl.PluginClassLoader
|
||||
import com.intellij.platform.testFramework.PluginBuilder
|
||||
import com.intellij.platform.plugins.testFramework.PluginSetTestBuilder
|
||||
import com.intellij.testFramework.LoggedErrorProcessor
|
||||
import com.intellij.testFramework.assertions.Assertions.assertThat
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
package com.intellij.ide.plugins
|
||||
|
||||
import com.intellij.openapi.diagnostic.logger
|
||||
import com.intellij.platform.testFramework.PluginBuilder
|
||||
import com.intellij.platform.testFramework.loadAndInitDescriptorInTest
|
||||
import com.intellij.openapi.util.BuildNumber
|
||||
import com.intellij.testFramework.PlatformTestUtil
|
||||
import com.intellij.testFramework.TestDataPath
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.intellij.platform.plugins.parser.impl.PluginDescriptorFromXmlStreamCo
|
||||
import com.intellij.platform.plugins.parser.impl.ReadModuleContext
|
||||
import com.intellij.platform.plugins.parser.impl.XIncludeLoader.LoadedXIncludeReference
|
||||
import com.intellij.platform.plugins.parser.impl.consume
|
||||
import com.intellij.platform.testFramework.loadAndInitDescriptorInTest
|
||||
import com.intellij.testFramework.PlatformTestUtil
|
||||
import com.intellij.testFramework.TestDataPath
|
||||
import com.intellij.testFramework.UsefulTestCase
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.intellij.ide.plugins
|
||||
|
||||
import com.intellij.openapi.util.BuildNumber
|
||||
import com.intellij.platform.plugins.testFramework.PluginSetTestBuilder
|
||||
import com.intellij.platform.testFramework.PluginBuilder
|
||||
import com.intellij.testFramework.rules.InMemoryFsRule
|
||||
import com.intellij.util.io.write
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
|
||||
@@ -9,6 +9,8 @@ import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.openapi.util.registry.RegistryKeyBean
|
||||
import com.intellij.openapi.util.registry.RegistryKeyDescriptor
|
||||
import com.intellij.platform.testFramework.PluginBuilder
|
||||
import com.intellij.platform.testFramework.loadPluginWithText
|
||||
import com.intellij.testFramework.*
|
||||
import com.intellij.testFramework.rules.InMemoryFsRule
|
||||
import com.intellij.util.io.Ksuid
|
||||
|
||||
@@ -5,7 +5,7 @@ import com.intellij.configurationStore.getPerOsSettingsStorageFolderName
|
||||
import com.intellij.diagnostic.VMOptions
|
||||
import com.intellij.ide.SpecialConfigFiles
|
||||
import com.intellij.ide.plugins.DisabledPluginsState.Companion.saveDisabledPluginsAndInvalidate
|
||||
import com.intellij.ide.plugins.PluginBuilder
|
||||
import com.intellij.platform.testFramework.PluginBuilder
|
||||
import com.intellij.ide.plugins.PluginNode
|
||||
import com.intellij.ide.plugins.marketplace.MarketplacePluginDownloadService
|
||||
import com.intellij.ide.plugins.marketplace.utils.MarketplaceCustomizationService
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// 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.vfs.local;
|
||||
|
||||
import com.intellij.ide.plugins.DynamicPluginsTestUtil;
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
@@ -22,6 +21,7 @@ import com.intellij.openapi.vfs.newvfs.BulkFileListener;
|
||||
import com.intellij.openapi.vfs.newvfs.VfsImplUtil;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
|
||||
import com.intellij.platform.testFramework.DynamicPluginTestUtilsKt;
|
||||
import com.intellij.testFramework.EdtTestUtil;
|
||||
import com.intellij.testFramework.PlatformTestUtil;
|
||||
import com.intellij.testFramework.TestActionEvent;
|
||||
@@ -370,7 +370,7 @@ public class JarFileSystemTest extends BareTestFixtureTestCase {
|
||||
EdtTestUtil.runInEdtAndWait(() -> {
|
||||
assertNotNull(LocalFileSystem.getInstance().refreshAndFindFileByNioFile(copiedJar));
|
||||
|
||||
var fsRegistration = DynamicPluginsTestUtil.loadExtensionWithText(fsExtText, "com.intellij");
|
||||
var fsRegistration = DynamicPluginTestUtilsKt.loadExtensionWithText(fsExtText, "com.intellij");
|
||||
try {
|
||||
Disposer.register(fsRegistration, JarFileSystemImpl::cleanupForNextTest);
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
package com.intellij.openapi.vfs.newvfs.persistent;
|
||||
|
||||
import com.intellij.CacheSwitcher;
|
||||
import com.intellij.ide.plugins.DynamicPluginsTestUtil;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
@@ -31,6 +30,7 @@ import com.intellij.openapi.vfs.newvfs.*;
|
||||
import com.intellij.openapi.vfs.newvfs.events.*;
|
||||
import com.intellij.openapi.vfs.newvfs.impl.VirtualDirectoryImpl;
|
||||
import com.intellij.openapi.vfs.newvfs.impl.VirtualFileSystemEntry;
|
||||
import com.intellij.platform.testFramework.DynamicPluginTestUtilsKt;
|
||||
import com.intellij.testFramework.*;
|
||||
import com.intellij.testFramework.fixtures.BareTestFixtureTestCase;
|
||||
import com.intellij.testFramework.rules.TempDirectory;
|
||||
@@ -748,7 +748,7 @@ public class PersistentFsTest extends BareTestFixtureTestCase {
|
||||
String text = "<virtualFileSystem implementationClass=\"" +
|
||||
TracingJarFileSystemTestWrapper.class.getName() +
|
||||
"\" key=\"jar-wrapper\" physical=\"true\"/>";
|
||||
Disposable disposable = runInEdtAndGet(() -> DynamicPluginsTestUtil.loadExtensionWithText(text, "com.intellij"));
|
||||
Disposable disposable = runInEdtAndGet(() -> DynamicPluginTestUtilsKt.loadExtensionWithText(text, "com.intellij"));
|
||||
|
||||
try {
|
||||
File generationDir = tempDirectory.newDirectory("gen");
|
||||
@@ -795,7 +795,7 @@ public class PersistentFsTest extends BareTestFixtureTestCase {
|
||||
String text = "<virtualFileSystem implementationClass=\"" +
|
||||
TracingJarFileSystemTestWrapper.class.getName() +
|
||||
"\" key=\"jar-wrapper\" physical=\"true\"/>";
|
||||
Disposable disposable = runInEdtAndGet(() -> DynamicPluginsTestUtil.loadExtensionWithText(text, "com.intellij"));
|
||||
Disposable disposable = runInEdtAndGet(() -> DynamicPluginTestUtilsKt.loadExtensionWithText(text, "com.intellij"));
|
||||
|
||||
try {
|
||||
File generationDir = tempDirectory.newDirectory("gen");
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
@file:JvmName("DynamicPluginsTestUtil")
|
||||
@file:Suppress("UsePropertyAccessSyntax")
|
||||
package com.intellij.ide.plugins
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.platform.testFramework
|
||||
|
||||
import com.intellij.ide.plugins.DynamicPlugins
|
||||
import com.intellij.ide.plugins.IdeaPluginDescriptorImpl
|
||||
import com.intellij.ide.plugins.PluginDescriptorLoadingContext
|
||||
import com.intellij.ide.plugins.PluginInitializationContext
|
||||
import com.intellij.ide.plugins.PluginManagerCore
|
||||
import com.intellij.ide.plugins.loadDescriptorFromFileOrDirInTests
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.extensions.PluginId
|
||||
import com.intellij.openapi.util.BuildNumber
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.testFramework.IndexingTestUtil
|
||||
import com.intellij.testFramework.assertions.Assertions.assertThat
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
|
||||
@JvmOverloads
|
||||
internal fun loadAndInitDescriptorInTest(
|
||||
fun loadAndInitDescriptorInTest(
|
||||
dir: Path,
|
||||
isBundled: Boolean = false,
|
||||
disabledPlugins: Set<String> = emptySet(),
|
||||
@@ -59,7 +63,7 @@ fun loadExtensionWithText(extensionTag: String, ns: String = "com.intellij"): Di
|
||||
}
|
||||
}
|
||||
|
||||
internal fun loadPluginWithText(
|
||||
fun loadPluginWithText(
|
||||
pluginBuilder: PluginBuilder,
|
||||
path: Path,
|
||||
disabledPlugins: Set<String> = emptySet(),
|
||||
@@ -86,7 +90,7 @@ internal fun loadPluginWithText(
|
||||
}
|
||||
}
|
||||
|
||||
internal fun loadAndInitDescriptorInTest(
|
||||
fun loadAndInitDescriptorInTest(
|
||||
pluginBuilder: PluginBuilder,
|
||||
rootPath: Path,
|
||||
disabledPlugins: Set<String> = emptySet(),
|
||||
@@ -106,7 +110,7 @@ internal fun loadAndInitDescriptorInTest(
|
||||
)
|
||||
}
|
||||
|
||||
internal fun setPluginClassLoaderForMainAndSubPlugins(rootDescriptor: IdeaPluginDescriptorImpl, classLoader: ClassLoader?) {
|
||||
fun setPluginClassLoaderForMainAndSubPlugins(rootDescriptor: IdeaPluginDescriptorImpl, classLoader: ClassLoader?) {
|
||||
rootDescriptor.pluginClassLoader = classLoader
|
||||
for (dependency in rootDescriptor.dependencies) {
|
||||
dependency.subDescriptor?.let {
|
||||
@@ -115,7 +119,7 @@ internal fun setPluginClassLoaderForMainAndSubPlugins(rootDescriptor: IdeaPlugin
|
||||
}
|
||||
}
|
||||
|
||||
internal fun unloadAndUninstallPlugin(descriptor: IdeaPluginDescriptorImpl): Boolean {
|
||||
fun unloadAndUninstallPlugin(descriptor: IdeaPluginDescriptorImpl): Boolean {
|
||||
return DynamicPlugins.unloadPlugin(
|
||||
descriptor,
|
||||
DynamicPlugins.UnloadPluginOptions(disable = false),
|
||||
@@ -0,0 +1,332 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.platform.testFramework
|
||||
|
||||
import com.intellij.ide.plugins.ModuleDependencies
|
||||
import com.intellij.ide.plugins.ModuleLoadingRule
|
||||
import com.intellij.ide.plugins.PluginContentDescriptor
|
||||
import com.intellij.ide.plugins.PluginManagerCore
|
||||
import com.intellij.openapi.extensions.PluginId
|
||||
import com.intellij.util.io.Compressor
|
||||
import com.intellij.util.io.createParentDirectories
|
||||
import com.intellij.util.io.write
|
||||
import org.intellij.lang.annotations.Language
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.OutputStream
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import kotlin.io.path.createDirectories
|
||||
|
||||
|
||||
/** Constants from [com.intellij.platform.plugins.parser.impl.PluginXmlConst]
|
||||
* We can't access PluginXmlConst directly because it's in an implementation module */
|
||||
private object PluginBuilderConsts {
|
||||
const val PLUGIN_IMPLEMENTATION_DETAIL_ATTR: String = "implementation-detail"
|
||||
const val PLUGIN_PACKAGE_ATTR: String = "package"
|
||||
}
|
||||
|
||||
|
||||
private val pluginIdCounter = AtomicInteger()
|
||||
|
||||
class PluginBuilder private constructor() {
|
||||
private data class ExtensionBlock(val ns: String, val text: String)
|
||||
private data class DependsTag(val pluginId: String, val configFile: String?)
|
||||
|
||||
// counter is used to reduce plugin id length
|
||||
var id: String = "p_${pluginIdCounter.incrementAndGet()}"
|
||||
private set
|
||||
|
||||
private var implementationDetail = false
|
||||
private var separateJar = false
|
||||
private var name: String? = null
|
||||
private var description: String? = null
|
||||
private var packagePrefix: String? = null
|
||||
private val dependsTags = mutableListOf<DependsTag>()
|
||||
private var applicationListeners: String? = null
|
||||
private var resourceBundleBaseName: String? = null
|
||||
private var actions: String? = null
|
||||
private val extensions = mutableListOf<ExtensionBlock>()
|
||||
private var extensionPoints: String? = null
|
||||
private var untilBuild: String? = null
|
||||
private var sinceBuild: String? = null
|
||||
private var version: String? = null
|
||||
private val pluginAliases = mutableListOf<String>()
|
||||
|
||||
private val content = mutableListOf<PluginContentDescriptor.ModuleItem>()
|
||||
private val dependencies = mutableListOf<ModuleDependencies.ModuleReference>()
|
||||
private val pluginDependencies = mutableListOf<ModuleDependencies.PluginReference>()
|
||||
private val incompatibleWith = mutableListOf<ModuleDependencies.PluginReference>()
|
||||
|
||||
private data class SubDescriptor(val filename: String, val builder: PluginBuilder)
|
||||
|
||||
private val subDescriptors = ArrayList<SubDescriptor>()
|
||||
|
||||
fun dependsIntellijModulesLang(): PluginBuilder {
|
||||
depends("com.intellij.modules.lang")
|
||||
return this
|
||||
}
|
||||
|
||||
fun id(id: String): PluginBuilder {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
fun randomId(idPrefix: String): PluginBuilder {
|
||||
this.id = "${idPrefix}_${pluginIdCounter.incrementAndGet()}"
|
||||
return this
|
||||
}
|
||||
|
||||
fun name(name: String): PluginBuilder {
|
||||
this.name = name
|
||||
return this
|
||||
}
|
||||
|
||||
fun description(description: String): PluginBuilder {
|
||||
this.description = description
|
||||
return this
|
||||
}
|
||||
|
||||
fun packagePrefix(value: String?): PluginBuilder {
|
||||
packagePrefix = value
|
||||
return this
|
||||
}
|
||||
|
||||
fun separateJar(value: Boolean): PluginBuilder {
|
||||
separateJar = value
|
||||
return this
|
||||
}
|
||||
|
||||
fun depends(pluginId: String, configFile: String? = null): PluginBuilder {
|
||||
dependsTags.add(DependsTag(pluginId, configFile))
|
||||
return this
|
||||
}
|
||||
|
||||
fun depends(pluginId: String, subDescriptor: PluginBuilder, filename: String? = null): PluginBuilder {
|
||||
val fileName = filename ?: "dep_${pluginIdCounter.incrementAndGet()}.xml"
|
||||
subDescriptors.add(SubDescriptor(PluginManagerCore.META_INF + fileName, subDescriptor))
|
||||
depends(pluginId, fileName)
|
||||
return this
|
||||
}
|
||||
|
||||
fun module(
|
||||
moduleName: String, moduleDescriptor: PluginBuilder, loadingRule: ModuleLoadingRule = ModuleLoadingRule.OPTIONAL,
|
||||
moduleFile: String = "$moduleName.xml",
|
||||
): PluginBuilder {
|
||||
subDescriptors.add(SubDescriptor(moduleFile, moduleDescriptor))
|
||||
content.add(PluginContentDescriptor.ModuleItem(name = moduleName, configFile = null, descriptorContent = null, loadingRule = loadingRule))
|
||||
return this
|
||||
}
|
||||
|
||||
fun pluginAlias(alias: String): PluginBuilder {
|
||||
pluginAliases.add(alias)
|
||||
return this
|
||||
}
|
||||
|
||||
fun dependency(moduleName: String): PluginBuilder {
|
||||
dependencies.add(ModuleDependencies.ModuleReference(moduleName))
|
||||
return this
|
||||
}
|
||||
|
||||
fun pluginDependency(pluginId: String): PluginBuilder {
|
||||
pluginDependencies.add(ModuleDependencies.PluginReference(PluginId.getId(pluginId)))
|
||||
return this
|
||||
}
|
||||
|
||||
fun incompatibleWith(pluginId: String): PluginBuilder {
|
||||
incompatibleWith.add(ModuleDependencies.PluginReference(PluginId.getId(pluginId)))
|
||||
return this
|
||||
}
|
||||
|
||||
fun resourceBundle(resourceBundle: String?): PluginBuilder {
|
||||
resourceBundleBaseName = resourceBundle
|
||||
return this
|
||||
}
|
||||
|
||||
fun untilBuild(buildNumber: String): PluginBuilder {
|
||||
untilBuild = buildNumber
|
||||
return this
|
||||
}
|
||||
|
||||
fun sinceBuild(buildNumber: String): PluginBuilder {
|
||||
sinceBuild = buildNumber
|
||||
return this
|
||||
}
|
||||
|
||||
fun version(version: String): PluginBuilder {
|
||||
this.version = version
|
||||
return this
|
||||
}
|
||||
|
||||
fun applicationListeners(text: String): PluginBuilder {
|
||||
applicationListeners = text
|
||||
return this
|
||||
}
|
||||
|
||||
fun actions(text: String): PluginBuilder {
|
||||
actions = text
|
||||
return this
|
||||
}
|
||||
|
||||
fun extensions(text: String, ns: String = "com.intellij"): PluginBuilder {
|
||||
extensions.add(ExtensionBlock(ns, text))
|
||||
return this
|
||||
}
|
||||
|
||||
fun extensionPoints(@Language("XML") text: String): PluginBuilder {
|
||||
extensionPoints = text
|
||||
return this
|
||||
}
|
||||
|
||||
fun implementationDetail(): PluginBuilder {
|
||||
implementationDetail = true
|
||||
return this
|
||||
}
|
||||
|
||||
fun text(requireId: Boolean = true): String {
|
||||
return buildString {
|
||||
append("<idea-plugin")
|
||||
if (implementationDetail) {
|
||||
append(""" ${PluginBuilderConsts.PLUGIN_IMPLEMENTATION_DETAIL_ATTR}="true"""")
|
||||
}
|
||||
packagePrefix?.let {
|
||||
append(""" ${PluginBuilderConsts.PLUGIN_PACKAGE_ATTR}="$it"""")
|
||||
}
|
||||
if (separateJar) {
|
||||
append(""" separate-jar="true"""") // todo change to const from xml reader
|
||||
}
|
||||
append(">")
|
||||
if (requireId) {
|
||||
append("<id>$id</id>")
|
||||
}
|
||||
name?.let { append("<name>$it</name>") }
|
||||
description?.let { append("<description>$it</description>") }
|
||||
for (dependsTag in dependsTags) {
|
||||
val configFile = dependsTag.configFile
|
||||
if (configFile != null) {
|
||||
append("""<depends optional="true" config-file="$configFile">${dependsTag.pluginId}</depends>""")
|
||||
}
|
||||
else {
|
||||
append("<depends>${dependsTag.pluginId}</depends>")
|
||||
}
|
||||
}
|
||||
version?.let { append("<version>$it</version>") }
|
||||
|
||||
if (sinceBuild != null && untilBuild != null) {
|
||||
append("""<idea-version since-build="${sinceBuild}" until-build="${untilBuild}"/>""")
|
||||
}
|
||||
else if (sinceBuild != null) {
|
||||
append("""<idea-version since-build="${sinceBuild}"/>""")
|
||||
}
|
||||
else if (untilBuild != null) {
|
||||
append("""<idea-version until-build="${untilBuild}"/>""")
|
||||
}
|
||||
|
||||
for (extensionBlock in extensions) {
|
||||
append("""<extensions defaultExtensionNs="${extensionBlock.ns}">${extensionBlock.text}</extensions>""")
|
||||
}
|
||||
extensionPoints?.let { append("<extensionPoints>$it</extensionPoints>") }
|
||||
applicationListeners?.let { append("<applicationListeners>$it</applicationListeners>") }
|
||||
resourceBundleBaseName?.let { append("""<resource-bundle>$it</resource-bundle>""") }
|
||||
actions?.let { append("<actions>$it</actions>") }
|
||||
|
||||
if (content.isNotEmpty()) {
|
||||
append("\n<content>\n ")
|
||||
content.joinTo(this, separator = "\n ") { moduleItem ->
|
||||
val loadingAttribute = when (moduleItem.loadingRule) {
|
||||
ModuleLoadingRule.OPTIONAL -> ""
|
||||
ModuleLoadingRule.REQUIRED -> "loading=\"required\" "
|
||||
ModuleLoadingRule.EMBEDDED -> "loading=\"embedded\" "
|
||||
ModuleLoadingRule.ON_DEMAND -> "loading=\"on-demand\" "
|
||||
}
|
||||
"""<module name="${moduleItem.name}" $loadingAttribute/>"""
|
||||
}
|
||||
append("\n</content>")
|
||||
}
|
||||
|
||||
if (incompatibleWith.isNotEmpty()) {
|
||||
incompatibleWith.joinTo(this, separator = "\n ") {
|
||||
"""<incompatible-with>${it.id}</incompatible-with>"""
|
||||
}
|
||||
}
|
||||
|
||||
if (dependencies.isNotEmpty() || pluginDependencies.isNotEmpty()) {
|
||||
append("\n<dependencies>\n ")
|
||||
if (dependencies.isNotEmpty()) {
|
||||
dependencies.joinTo(this, separator = "\n ") { """<module name="${it.name}" />""" }
|
||||
}
|
||||
if (pluginDependencies.isNotEmpty()) {
|
||||
pluginDependencies.joinTo(this, separator = "\n ") { """<plugin id="${it.id}" />""" }
|
||||
}
|
||||
append("\n</dependencies>")
|
||||
}
|
||||
|
||||
for (alias in pluginAliases) {
|
||||
append("\n")
|
||||
append("""<module value="$alias"/>""")
|
||||
}
|
||||
|
||||
append("</idea-plugin>")
|
||||
}
|
||||
}
|
||||
|
||||
fun build(path: Path): PluginBuilder {
|
||||
val allDescriptors = collectAllSubDescriptors(subDescriptors).toList()
|
||||
if (allDescriptors.any { it.builder.separateJar }) {
|
||||
val modulesDir = path.resolve("lib/modules")
|
||||
modulesDir.createDirectories()
|
||||
buildJar(path.resolve("lib/$id.jar"))
|
||||
for ((fileName, subDescriptor) in allDescriptors) {
|
||||
if (subDescriptor.separateJar) {
|
||||
val jarPath = modulesDir.resolve("${fileName.removeSuffix(".xml")}.jar")
|
||||
subDescriptor.buildJarToStream(Files.newOutputStream(jarPath), mainDescriptorRelativePath = fileName)
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
path.resolve(PluginManagerCore.PLUGIN_XML_PATH).write(text())
|
||||
for (subDescriptor in allDescriptors) {
|
||||
path.resolve(subDescriptor.filename).createParentDirectories().write(subDescriptor.builder.text(requireId = false))
|
||||
}
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
private fun collectAllSubDescriptors(descriptors: List<SubDescriptor>): Sequence<SubDescriptor> {
|
||||
return descriptors.asSequence().flatMap { sequenceOf(it) + collectAllSubDescriptors(it.builder.subDescriptors) }
|
||||
}
|
||||
|
||||
fun buildJar(path: Path): PluginBuilder {
|
||||
buildJarToStream(Files.newOutputStream(path), PluginManagerCore.PLUGIN_XML_PATH)
|
||||
return this
|
||||
}
|
||||
|
||||
private fun buildJarToStream(outputStream: OutputStream, mainDescriptorRelativePath: String) {
|
||||
Compressor.Zip(outputStream).use {
|
||||
it.addFile(mainDescriptorRelativePath, text(requireId = mainDescriptorRelativePath == PluginManagerCore.PLUGIN_XML_PATH).toByteArray())
|
||||
for ((fileName, subDescriptor) in subDescriptors) {
|
||||
if (!subDescriptor.separateJar) {
|
||||
it.addFile(fileName, subDescriptor.text(requireId = false).toByteArray())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun buildZip(path: Path): PluginBuilder {
|
||||
val jarStream = ByteArrayOutputStream()
|
||||
buildJarToStream(jarStream, PluginManagerCore.PLUGIN_XML_PATH)
|
||||
|
||||
val pluginName = name ?: id
|
||||
Compressor.Zip(Files.newOutputStream(path)).use {
|
||||
it.addDirectory(pluginName)
|
||||
it.addDirectory("$pluginName/lib")
|
||||
it.addFile("$pluginName/lib/$pluginName.jar", jarStream.toByteArray())
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun withModulesLang(): PluginBuilder = PluginBuilder().dependsIntellijModulesLang()
|
||||
fun empty(): PluginBuilder = PluginBuilder()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user