First take on associating plugins with dependencies (IJP-877)

GitOrigin-RevId: 037a1edb2bc2f24d1c74f40ed5f5f9c8066c0635
This commit is contained in:
Dmitry Jemerov
2021-05-12 18:59:11 +02:00
committed by intellij-monorepo-bot
parent 8c31def6da
commit 49b08ff66b
16 changed files with 121 additions and 18 deletions

View File

@@ -1,4 +1,4 @@
// 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. // Copyright 2000-2021 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.packaging.impl.artifacts; package com.intellij.packaging.impl.artifacts;
import com.intellij.compiler.server.BuildManager; import com.intellij.compiler.server.BuildManager;
@@ -265,7 +265,7 @@ public final class ArtifactManagerImpl extends ArtifactManager implements Persis
@Nls(capitalization = Nls.Capitalization.Sentence) String errorMessage) { @Nls(capitalization = Nls.Capitalization.Sentence) String errorMessage) {
final InvalidArtifactImpl artifact = new InvalidArtifactImpl(state, errorMessage, externalSource); final InvalidArtifactImpl artifact = new InvalidArtifactImpl(state, errorMessage, externalSource);
ProjectLoadingErrorsNotifier.getInstance(myProject).registerError(new ArtifactLoadingErrorDescription(myProject, artifact)); ProjectLoadingErrorsNotifier.getInstance(myProject).registerError(new ArtifactLoadingErrorDescription(myProject, artifact));
UnknownFeaturesCollector.getInstance(myProject).registerUnknownFeature(FEATURE_TYPE, state.getArtifactType(), "Artifact"); UnknownFeaturesCollector.getInstance(myProject).registerUnknownFeature(FEATURE_TYPE, state.getArtifactType(), JavaCompilerBundle.message("plugins.advertiser.feature.artifact"));
return artifact; return artifact;
} }

View File

@@ -321,3 +321,4 @@ notification.title.cpu.snapshot.build.has.been.captured=Build CPU snapshot has b
action.show.snapshot.location.text=Show Snapshot Location action.show.snapshot.location.text=Show Snapshot Location
dialog.message.failed.to.determine.host.ip.for.wsl.jdk=Failed to determine host IP for WSL JDK dialog.message.failed.to.determine.host.ip.for.wsl.jdk=Failed to determine host IP for WSL JDK
progress.preparing.wsl.build.environment=Preparing WSL build environment... progress.preparing.wsl.build.environment=Preparing WSL build environment...
plugins.advertiser.feature.artifact=artifact

View File

@@ -2154,6 +2154,8 @@
<registryKey key="starters.dependency.update.host" <registryKey key="starters.dependency.update.host"
defaultValue="https://frameworks.jetbrains.com" defaultValue="https://frameworks.jetbrains.com"
description="The host is used to download dependency config updates for framework starters"/> description="The host is used to download dependency config updates for framework starters"/>
<dependencyCollector implementation="com.intellij.ide.JavaDependencyCollector"/>
</extensions> </extensions>
<extensions defaultExtensionNs="org.jetbrains"> <extensions defaultExtensionNs="org.jetbrains">

View File

@@ -0,0 +1,35 @@
// Copyright 2000-2021 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.ide
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.rootManager
import com.intellij.openapi.roots.LibraryOrderEntry
import com.intellij.openapi.roots.impl.libraries.LibraryEx
import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar
import com.intellij.ide.plugins.DependencyCollector
import org.jetbrains.idea.maven.utils.library.RepositoryLibraryProperties
class JavaDependencyCollector : DependencyCollector {
override val dependencyKind: String
get() = "java"
override fun collectDependencies(project: Project): List<String> {
val projectLibraryTable = LibraryTablesRegistrar.getInstance().getLibraryTable(project)
val result = mutableSetOf<String>()
for (library in projectLibraryTable.libraries) {
val properties = (library as? LibraryEx)?.properties as? RepositoryLibraryProperties ?: continue
result.add(properties.groupId + ":" + properties.artifactId)
}
for (module in ModuleManager.getInstance(project).modules) {
for (orderEntry in module.rootManager.orderEntries) {
if (orderEntry is LibraryOrderEntry && orderEntry.isModuleLevel) {
val library = orderEntry.library
val properties = (library as? LibraryEx)?.properties as? RepositoryLibraryProperties ?: continue
result.add(properties.groupId + ":" + properties.artifactId)
}
}
}
return result.toList()
}
}

View File

@@ -8,6 +8,7 @@ import com.intellij.execution.configurations.*
import com.intellij.execution.runners.ExecutionEnvironment import com.intellij.execution.runners.ExecutionEnvironment
import com.intellij.execution.runners.ExecutionUtil import com.intellij.execution.runners.ExecutionUtil
import com.intellij.execution.runners.ProgramRunner import com.intellij.execution.runners.ProgramRunner
import com.intellij.ide.IdeBundle
import com.intellij.ide.plugins.DynamicPluginListener import com.intellij.ide.plugins.DynamicPluginListener
import com.intellij.ide.plugins.IdeaPluginDescriptor import com.intellij.ide.plugins.IdeaPluginDescriptor
import com.intellij.ide.util.PropertiesComponent import com.intellij.ide.util.PropertiesComponent
@@ -999,7 +1000,7 @@ open class RunManagerImpl @JvmOverloads constructor(val project: Project, shared
if (checkUnknown && typeId != null) { if (checkUnknown && typeId != null) {
UnknownFeaturesCollector.getInstance(project).registerUnknownFeature( UnknownFeaturesCollector.getInstance(project).registerUnknownFeature(
CONFIGURATION_TYPE_FEATURE_ID, CONFIGURATION_TYPE_FEATURE_ID,
"Run Configuration", ExecutionBundle.message("plugins.advertiser.feature.run.configuration"),
typeId, typeId,
factoryId ?: typeId, factoryId ?: typeId,
) )

View File

@@ -604,4 +604,6 @@ startup.tasks.confirmation.notification.action.review=Review
edit.configuration.templates=Edit configuration templates... edit.configuration.templates=Edit configuration templates...
progress.title.patch.java.command.line.parameters=Patch Java command line parameters progress.title.patch.java.command.line.parameters=Patch Java command line parameters
status.text.add.new.run.configuration=Add new run configuration... status.text.add.new.run.configuration=Add new run configuration...
status.text.or.select.run.configuration.to.edit=or select run configuration to edit status.text.or.select.run.configuration.to.edit=or select run configuration to edit
plugins.advertiser.feature.run.configuration=run configuration

View File

@@ -1,4 +1,4 @@
// 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. // Copyright 2000-2021 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.facet; package com.intellij.facet;
import com.intellij.facet.impl.FacetEventsPublisher; import com.intellij.facet.impl.FacetEventsPublisher;
@@ -11,6 +11,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module; import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ProjectLoadingErrorsNotifier; import com.intellij.openapi.module.ProjectLoadingErrorsNotifier;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.UnknownFeaturesCollector; import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.UnknownFeaturesCollector;
import com.intellij.openapi.util.NlsContexts; import com.intellij.openapi.util.NlsContexts;
import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.StringUtil;
@@ -140,7 +141,7 @@ public abstract class FacetManagerBase extends FacetManager {
FacetLoadingErrorDescription description = new FacetLoadingErrorDescription(facet); FacetLoadingErrorDescription description = new FacetLoadingErrorDescription(facet);
ProjectLoadingErrorsNotifier.getInstance(project).registerError(description); ProjectLoadingErrorsNotifier.getInstance(project).registerError(description);
if (unknownType) { if (unknownType) {
UnknownFeaturesCollector.getInstance(project).registerUnknownFeature(FEATURE_TYPE, state.getFacetType(), "Facet"); UnknownFeaturesCollector.getInstance(project).registerUnknownFeature(FEATURE_TYPE, state.getFacetType(), ProjectBundle.message("plugins.advertiser.feature.facet"));
} }
} }
} }

View File

@@ -1629,6 +1629,7 @@ plugins.advertiser.action.ignore.ultimate=Do not suggest Ultimate
plugins.advertiser.ultimate.features.detected=Features covered by IntelliJ IDEA Ultimate {0} are detected plugins.advertiser.ultimate.features.detected=Features covered by IntelliJ IDEA Ultimate {0} are detected
plugins.advertiser.missing.feature={0,choice,1#Plugin|2#Plugins} supporting {1} ''{2}'' {0,choice,1#is|2#are} currently {3,choice,0#disabled|1#not installed}. plugins.advertiser.missing.feature={0,choice,1#Plugin|2#Plugins} supporting {1} ''{2}'' {0,choice,1#is|2#are} currently {3,choice,0#disabled|1#not installed}.
plugins.advertiser.missing.features={0,choice,1#Plugin|2#Plugins} supporting features ({1}) {0,choice,1#is|2#are} currently {2,choice,0#disabled|1#not installed}. plugins.advertiser.missing.features={0,choice,1#Plugin|2#Plugins} supporting features ({1}) {0,choice,1#is|2#are} currently {2,choice,0#disabled|1#not installed}.
plugins.advertiser.feature.dependency=dependency
do.not.ask.me.again=Don't ask again do.not.ask.me.again=Don't ask again

View File

@@ -283,3 +283,4 @@ list.item.group.by.type=Type
list.item.group.by.directory=Directory list.item.group.by.directory=Directory
label.directory.will.be.excluded.from.framework.detection=''{0}'' directory will be excluded from framework detection label.directory.will.be.excluded.from.framework.detection=''{0}'' directory will be excluded from framework detection
label.framework.detection.will.be.disabled=''{0}'' framework detection will be disabled. label.framework.detection.will.be.disabled=''{0}'' framework detection will be disabled.
plugins.advertiser.feature.facet=facet

View File

@@ -15,9 +15,6 @@ import com.intellij.util.xmlb.annotations.XMap
storages = [Storage(StoragePathMacros.CACHE_FILE, roamingType = RoamingType.DISABLED)], storages = [Storage(StoragePathMacros.CACHE_FILE, roamingType = RoamingType.DISABLED)],
) )
class PluginFeatureService : SimplePersistentStateComponent<PluginFeatureService.State>(State()) { class PluginFeatureService : SimplePersistentStateComponent<PluginFeatureService.State>(State()) {
private val featureMappingsCollected = mutableSetOf<String>()
@Tag("features") @Tag("features")
class FeaturePluginsList : BaseState() { class FeaturePluginsList : BaseState() {
@@ -65,8 +62,6 @@ class PluginFeatureService : SimplePersistentStateComponent<PluginFeatureService
idMapping: (T) -> String, idMapping: (T) -> String,
displayNameMapping: (T) -> String, displayNameMapping: (T) -> String,
) { ) {
if (!featureMappingsCollected.add(featureType)) return
val pluginsList = state[featureType] val pluginsList = state[featureType]
ep.processWithPluginDescriptor { ext, descriptor -> ep.processWithPluginDescriptor { ext, descriptor ->
pluginsList[idMapping(ext)] = FeaturePluginData( pluginsList[idMapping(ext)] = FeaturePluginData(

View File

@@ -14,7 +14,7 @@ class PluginData @JvmOverloads constructor(
@Attribute("fromCustomRepository") val isFromCustomRepository: Boolean = false, @Attribute("fromCustomRepository") val isFromCustomRepository: Boolean = false,
) : Comparable<PluginData> { ) : Comparable<PluginData> {
val pluginId: PluginId = PluginId.getId(pluginIdString) val pluginId: PluginId get() = PluginId.getId(pluginIdString)
val pluginName = nullablePluginName ?: pluginIdString val pluginName = nullablePluginName ?: pluginIdString

View File

@@ -0,0 +1,44 @@
// Copyright 2000-2021 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.ide.plugins
import com.intellij.openapi.extensions.ExtensionPointName
import com.intellij.openapi.project.Project
import com.intellij.openapi.startup.StartupActivity
import com.intellij.util.xmlb.annotations.Attribute
interface DependencyCollector {
val dependencyKind: String
fun collectDependencies(project: Project): List<String>
companion object {
val EP_NAME = ExtensionPointName.create<DependencyCollector>("com.intellij.dependencyCollector")
}
}
class DependencySupportBean {
@Attribute("kind")
@JvmField
var kind: String = ""
@Attribute("coordinate")
@JvmField
var coordinate: String = ""
companion object {
val EP_NAME = ExtensionPointName.create<DependencySupportBean>("com.intellij.dependencySupport")
}
}
const val DEPENDENCY_SUPPORT_FEATURE = "dependencySupport"
class DependencyFeatureCollector : StartupActivity.Background {
override fun runActivity(project: Project) {
PluginFeatureService.instance.collectFeatureMapping(
DEPENDENCY_SUPPORT_FEATURE,
DependencySupportBean.EP_NAME,
{ bean -> bean.kind + ":" + bean.coordinate },
{ bean -> bean.kind + ":" + bean.coordinate }
)
}
}

View File

@@ -29,7 +29,7 @@ open class PluginAdvertiserService {
fun run( fun run(
project: Project, project: Project,
customPlugins: List<PluginNode>, customPlugins: List<PluginNode>,
unknownFeatures: Set<UnknownFeature>, unknownFeatures: Collection<UnknownFeature>,
) { ) {
val features = MultiMap.createSet<PluginId, UnknownFeature>() val features = MultiMap.createSet<PluginId, UnknownFeature>()
val disabledPlugins = HashMap<PluginData, IdeaPluginDescriptor>() val disabledPlugins = HashMap<PluginData, IdeaPluginDescriptor>()

View File

@@ -1,6 +1,9 @@
// Copyright 2000-2021 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. // Copyright 2000-2021 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.updateSettings.impl.pluginsAdvertisement package com.intellij.openapi.updateSettings.impl.pluginsAdvertisement
import com.intellij.ide.IdeBundle
import com.intellij.ide.plugins.DEPENDENCY_SUPPORT_FEATURE
import com.intellij.ide.plugins.DependencyCollector
import com.intellij.ide.plugins.advertiser.KnownExtensions import com.intellij.ide.plugins.advertiser.KnownExtensions
import com.intellij.ide.plugins.advertiser.KnownExtensionsService import com.intellij.ide.plugins.advertiser.KnownExtensionsService
import com.intellij.ide.plugins.advertiser.PluginData import com.intellij.ide.plugins.advertiser.PluginData
@@ -9,7 +12,6 @@ import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.fileTypes.FileTypeFactory import com.intellij.openapi.fileTypes.FileTypeFactory
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.startup.StartupActivity import com.intellij.openapi.startup.StartupActivity
import com.intellij.openapi.updateSettings.impl.UpdateSettings
import com.intellij.ui.EditorNotifications import com.intellij.ui.EditorNotifications
internal class PluginsAdvertiserStartupActivity : StartupActivity.Background { internal class PluginsAdvertiserStartupActivity : StartupActivity.Background {
@@ -17,8 +19,7 @@ internal class PluginsAdvertiserStartupActivity : StartupActivity.Background {
override fun runActivity(project: Project) { override fun runActivity(project: Project) {
val application = ApplicationManager.getApplication() val application = ApplicationManager.getApplication()
if (application.isUnitTestMode || if (application.isUnitTestMode ||
application.isHeadlessEnvironment || application.isHeadlessEnvironment) {
!UpdateSettings.getInstance().isPluginsCheckNeeded) {
return return
} }
@@ -29,7 +30,10 @@ internal class PluginsAdvertiserStartupActivity : StartupActivity.Background {
val extensionsService = KnownExtensionsService.instance val extensionsService = KnownExtensionsService.instance
val extensions = extensionsService.extensions val extensions = extensionsService.extensions
val unknownFeatures = UnknownFeaturesCollector.getInstance(project).unknownFeatures
val unknownFeatures = UnknownFeaturesCollector.getInstance(project).unknownFeatures.toMutableList()
unknownFeatures.addAll(collectDependencyUnknownFeatures(project))
if (extensions != null && unknownFeatures.isEmpty()) { if (extensions != null && unknownFeatures.isEmpty()) {
return return
} }
@@ -54,6 +58,17 @@ internal class PluginsAdvertiserStartupActivity : StartupActivity.Background {
} }
} }
private fun collectDependencyUnknownFeatures(project: Project): List<UnknownFeature> {
return DependencyCollector.EP_NAME.extensions.flatMap { dependencyCollector ->
dependencyCollector.collectDependencies(project).map { coordinate ->
UnknownFeature(DEPENDENCY_SUPPORT_FEATURE,
IdeBundle.message("plugins.advertiser.feature.dependency"),
dependencyCollector.dependencyKind + ":" + coordinate,
coordinate)
}
}
}
companion object { companion object {
@JvmStatic @JvmStatic

View File

@@ -420,5 +420,8 @@
<!--suppress PluginXmlValidity --> <!--suppress PluginXmlValidity -->
<extensionPoint name="advancedSetting" beanClass="com.intellij.openapi.options.advanced.AdvancedSettingBean" dynamic="true"/> <extensionPoint name="advancedSetting" beanClass="com.intellij.openapi.options.advanced.AdvancedSettingBean" dynamic="true"/>
<extensionPoint name="dependencyCollector" interface="com.intellij.ide.plugins.DependencyCollector" dynamic="true"/>
<extensionPoint name="dependencySupport" beanClass="com.intellij.ide.plugins.DependencySupportBean" dynamic="true"/>
</extensionPoints> </extensionPoints>
</idea-plugin> </idea-plugin>

View File

@@ -1228,7 +1228,9 @@
<advancedSetting id="editor.soft.wrap.force.limit" default="100000" groupKey="group.advanced.settings.editor"/> <advancedSetting id="editor.soft.wrap.force.limit" default="100000" groupKey="group.advanced.settings.editor"/>
<advancedSetting id="terminal.buffer.max.lines.count" default="5000" groupKey="group.advanced.settings.terminal"/> <advancedSetting id="terminal.buffer.max.lines.count" default="5000" groupKey="group.advanced.settings.terminal"/>
<advancedSetting id="terminal.escape.moves.focus.to.editor" default="true" groupKey="group.advanced.settings.terminal"/> <advancedSetting id="terminal.escape.moves.focus.to.editor" default="true" groupKey="group.advanced.settings.terminal"/>
</extensions>
<backgroundPostStartupActivity implementation="com.intellij.ide.plugins.DependencyFeatureCollector"/>
/ </extensions>
<extensions defaultExtensionNs="org.jetbrains"> <extensions defaultExtensionNs="org.jetbrains">
<urlOpener implementation="com.intellij.ide.browsers.impl.DefaultUrlOpener" order="last"/> <urlOpener implementation="com.intellij.ide.browsers.impl.DefaultUrlOpener" order="last"/>
</extensions> </extensions>