mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-30 02:09:59 +07:00
[dependencies] feature collector for not loaded (on demand) plugins
GitOrigin-RevId: e7dbeead53df0119220fc8177f11b8aec44a72be
This commit is contained in:
committed by
intellij-monorepo-bot
parent
b00da45550
commit
e14f946b06
@@ -9,7 +9,9 @@ import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.components.*
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
@ApiStatus.Internal
|
||||
@Service(Service.Level.APP)
|
||||
@State(name = "PluginFeatureService", storages = [Storage(StoragePathMacros.CACHE_FILE)])
|
||||
class PluginFeatureService : SerializablePersistentStateComponent<PluginFeatureService.State>(State()) {
|
||||
@@ -36,7 +38,7 @@ class PluginFeatureService : SerializablePersistentStateComponent<PluginFeatureS
|
||||
idMapping: (T) -> String,
|
||||
displayNameMapping: (T) -> String,
|
||||
) {
|
||||
val featureMap = LinkedHashMap(featureMap(featureType))
|
||||
val featureMap = LinkedHashMap<String, FeaturePluginData>()
|
||||
|
||||
// fold
|
||||
ep.processWithPluginDescriptor { ext, descriptor ->
|
||||
@@ -48,15 +50,27 @@ class PluginFeatureService : SerializablePersistentStateComponent<PluginFeatureS
|
||||
featureMap.put(idMapping(ext), pluginData)
|
||||
}
|
||||
|
||||
updateFeatureMapping(featureType, featureMap)
|
||||
}
|
||||
|
||||
@ApiStatus.Experimental
|
||||
fun updateFeatureMapping(
|
||||
featureType: String,
|
||||
featureMap: Map<String, FeaturePluginData>,
|
||||
) {
|
||||
updateState { oldState ->
|
||||
State(oldState.features + (featureType to FeaturePluginList(featureMap)))
|
||||
val oldFeatures = oldState.features
|
||||
val newFeatureMap = LinkedHashMap(oldFeatures.getFeatureMap(featureType) ?: emptyMap()) +
|
||||
featureMap
|
||||
|
||||
State(oldFeatures + (featureType to FeaturePluginList(newFeatureMap)))
|
||||
}
|
||||
}
|
||||
|
||||
fun getPluginForFeature(
|
||||
featureType: String,
|
||||
implementationName: String,
|
||||
): FeaturePluginData? = featureMap(featureType).get(implementationName)
|
||||
): FeaturePluginData? = state.features.getFeatureMap(featureType)?.get(implementationName)
|
||||
|
||||
private fun featureMap(featureType: String) = state.features.get(featureType)?.featureMap ?: emptyMap()
|
||||
private fun Map<String, FeaturePluginList>.getFeatureMap(featureType: String) = get(featureType)?.featureMap
|
||||
}
|
||||
|
||||
@@ -10,8 +10,10 @@ import com.intellij.openapi.startup.ProjectPostStartupActivity
|
||||
import com.intellij.openapi.util.NlsSafe
|
||||
import com.intellij.serviceContainer.BaseKeyedLazyInstance
|
||||
import com.intellij.util.xmlb.annotations.Attribute
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
internal class DependencyCollectorBean : BaseKeyedLazyInstance<DependencyCollector>() {
|
||||
|
||||
@Attribute("kind")
|
||||
@JvmField
|
||||
@RequiredElement
|
||||
@@ -46,7 +48,8 @@ interface DependencyCollector {
|
||||
* Marks a plugin as supporting a given dependency. The `coordinate` attribute specifies the name or coordinate of the supported
|
||||
* library/dependency, in the same format as returned from [DependencyCollector.collectDependencies] for the respective dependency kind.
|
||||
*/
|
||||
internal class DependencySupportBean : PluginAware {
|
||||
internal class DependencySupportBean() : PluginAware {
|
||||
|
||||
private var pluginDescriptor: PluginDescriptor? = null
|
||||
|
||||
@Attribute("kind")
|
||||
@@ -71,6 +74,13 @@ internal class DependencySupportBean : PluginAware {
|
||||
val EP_NAME = ExtensionPointName.create<DependencySupportBean>("com.intellij.dependencySupport")
|
||||
}
|
||||
|
||||
@ApiStatus.Experimental
|
||||
internal constructor(attributes: Map<String, String>) : this() {
|
||||
kind = attributes["kind"]!!
|
||||
coordinate = attributes["coordinate"]!!
|
||||
displayName = attributes.getOrDefault("displayName", "")
|
||||
}
|
||||
|
||||
override fun setPluginDescriptor(pluginDescriptor: PluginDescriptor) {
|
||||
this.pluginDescriptor = pluginDescriptor
|
||||
}
|
||||
@@ -78,13 +88,20 @@ internal class DependencySupportBean : PluginAware {
|
||||
|
||||
internal const val DEPENDENCY_SUPPORT_FEATURE = "dependencySupport"
|
||||
|
||||
internal val DependencySupportBean.id: @NlsSafe String
|
||||
get() = "$kind:$coordinate"
|
||||
|
||||
internal val DependencySupportBean.displayNameOrId: @NlsSafe String
|
||||
get() = displayName.ifEmpty { id }
|
||||
|
||||
internal class DependencyFeatureCollector : ProjectPostStartupActivity {
|
||||
|
||||
override suspend fun execute(project: Project) {
|
||||
PluginFeatureService.instance.collectFeatureMapping(
|
||||
DEPENDENCY_SUPPORT_FEATURE,
|
||||
DependencySupportBean.EP_NAME,
|
||||
{ bean -> bean.kind + ":" + bean.coordinate },
|
||||
{ bean -> bean.displayName.ifEmpty { bean.kind + ":" + bean.coordinate } }
|
||||
{ it.id },
|
||||
{ it.displayNameOrId },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
// 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.ide.plugins.advertiser
|
||||
|
||||
import com.intellij.ide.plugins.*
|
||||
import com.intellij.openapi.extensions.ExtensionNotApplicableException
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.startup.ProjectPostStartupActivity
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
@ApiStatus.Experimental
|
||||
private class OnDemandDependencyFeatureCollector : ProjectPostStartupActivity {
|
||||
|
||||
init {
|
||||
if (!IdeaPluginDescriptorImpl.isOnDemandEnabled) {
|
||||
throw ExtensionNotApplicableException.create()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun execute(project: Project) {
|
||||
val featureMap = LinkedHashMap<String, FeaturePluginData>()
|
||||
|
||||
PluginManagerCore.getPluginSet()
|
||||
.allPlugins // todo modules
|
||||
.filter { it.pluginClassLoader == null }
|
||||
.filter { it.isOnDemand }
|
||||
.associateWith { it.epNameToExtensions?.get(DependencySupportBean.EP_NAME.name) ?: emptyList() }
|
||||
.forEach { (pluginDescriptor, extensionDescriptors) ->
|
||||
val pluginData = PluginData(pluginDescriptor)
|
||||
|
||||
featureMap += extensionDescriptors.mapNotNull { it.element }
|
||||
.map { DependencySupportBean(it.attributes) }
|
||||
.associate { bean ->
|
||||
bean.id to FeaturePluginData(bean.displayNameOrId, pluginData)
|
||||
}
|
||||
}
|
||||
|
||||
PluginFeatureService.instance.updateFeatureMapping(DEPENDENCY_SUPPORT_FEATURE, featureMap)
|
||||
}
|
||||
}
|
||||
@@ -1348,6 +1348,7 @@
|
||||
<advancedSetting id="documentation.components.enable.highlighting.of.links" default="false" groupKey="group.advanced.settings.documentation.components"/>
|
||||
|
||||
<backgroundPostStartupActivity implementation="com.intellij.ide.plugins.DependencyFeatureCollector"/>
|
||||
<backgroundPostStartupActivity implementation="com.intellij.ide.plugins.advertiser.OnDemandDependencyFeatureCollector"/>
|
||||
<projectService serviceInterface="com.intellij.presentation.FilePresentationService"
|
||||
serviceImplementation="com.intellij.presentation.impl.FilePresentationServiceImpl"/>
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<!--suppress PluginXmlValidity -->
|
||||
<idea-plugin package="org.jetbrains.idea.devkit.dummy">
|
||||
<idea-plugin package="org.jetbrains.idea.devkit.dummy"
|
||||
on-demand="true">
|
||||
<id>DevKit</id>
|
||||
<name>Plugin DevKit</name>
|
||||
<category>Plugin Development</category>
|
||||
|
||||
Reference in New Issue
Block a user