mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[devkit] IJPL-222037 Block new usages of preload services in plugins
GitOrigin-RevId: b38f94f0d99b5733e0d9313bbcab3da81e0f1adb
This commit is contained in:
committed by
intellij-monorepo-bot
parent
38d2b04dfb
commit
854db13b80
+1
-1
@@ -1489,9 +1489,9 @@ private fun executeRegisterTask(mainPluginDescriptor: IdeaPluginDescriptorImpl,
|
||||
|
||||
// Ask Core team approve before changing this set
|
||||
@Internal
|
||||
@VisibleForTesting
|
||||
@Suppress("ReplaceJavaStaticMethodWithKotlinAnalog")
|
||||
@Language("jvm-class-name")
|
||||
@JvmField
|
||||
val servicePreloadingAllowListForNonCorePlugin: Set<String> = java.util.Set.of(
|
||||
"com.intellij.compiler.server.BuildManager",
|
||||
"com.intellij.openapi.module.WebModuleTypeRegistrar",
|
||||
|
||||
@@ -212,6 +212,7 @@ inspections.plugin.xml.product.descriptor.invalid.version=Version must be an int
|
||||
inspections.plugin.xml.no.plugin.icon.svg.file=<html>Plugin should provide ''{0}'' (<a href="https://plugins.jetbrains.com/docs/intellij/plugin-icon-file.html?from=PluginXmlPluginLogoInspection">Documentation</a>)</html>
|
||||
inspections.plugin.xml.component.interface.class.redundant=Redundant tag 'interface-class'
|
||||
inspections.plugin.xml.service.interface.class.redundant=Redundant attribute 'serviceInterface'
|
||||
inspections.plugin.xml.service.preload.prohibited=Plugins may not use preloading, use <postStartupActivity> ProjectActivity, lazy MessageBus topics or specific extensions instead.
|
||||
inspections.plugin.xml.duplicated.dependency=Duplicate dependency configuration file ''{0}''
|
||||
inspections.plugin.xml.ComponentModuleRegistrationChecker.element.registered.wrong.module=Element should be registered in ''{0}'' module where its class ''{1}'' is defined
|
||||
inspections.plugin.xml.ComponentModuleRegistrationChecker.fix.move.registration.name=Move registration to {0}
|
||||
|
||||
+59
-10
@@ -12,12 +12,16 @@ import com.intellij.ide.util.PsiNavigationSupport;
|
||||
import com.intellij.lang.LanguageExtensionPoint;
|
||||
import com.intellij.openapi.components.ServiceDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiReferenceProviderBean;
|
||||
import com.intellij.psi.impl.source.resolve.reference.PsiReferenceContributorEP;
|
||||
import com.intellij.psi.stubs.StubElementTypeHolderEP;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.xml.XmlFile;
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.xml.DomElement;
|
||||
@@ -42,6 +46,9 @@ import org.jetbrains.idea.devkit.util.DevKitDomUtil;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.intellij.openapi.project.IntelliJProjectUtil.isIntelliJPlatformProject;
|
||||
import static com.intellij.serviceContainer.ComponentManagerImplKt.servicePreloadingAllowListForNonCorePlugin;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public final class PluginXmlExtensionRegistrationInspection extends DevKitPluginXmlInspectionBase {
|
||||
|
||||
@@ -94,16 +101,8 @@ public final class PluginXmlExtensionRegistrationInspection extends DevKitPlugin
|
||||
}
|
||||
|
||||
if (ServiceDescriptor.class.getName().equals(extensionPoint.getBeanClass().getStringValue())) {
|
||||
GenericAttributeValue<?> serviceInterface = DevKitDomUtil.getAttribute(extension, "serviceInterface");
|
||||
GenericAttributeValue<?> serviceImplementation = DevKitDomUtil.getAttribute(extension, "serviceImplementation");
|
||||
if (serviceInterface != null && serviceImplementation != null &&
|
||||
StringUtil.equals(serviceInterface.getStringValue(), serviceImplementation.getStringValue())) {
|
||||
if (hasMissingAttribute(extension, "testServiceImplementation")) {
|
||||
highlightRedundant(serviceInterface,
|
||||
DevKitBundle.message("inspections.plugin.xml.service.interface.class.redundant"),
|
||||
ProblemHighlightType.WARNING, holder);
|
||||
}
|
||||
}
|
||||
checkRedundantServiceInterface(holder, extension);
|
||||
checkPreloadUseProhibited(holder, extension);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -176,6 +175,56 @@ public final class PluginXmlExtensionRegistrationInspection extends DevKitPlugin
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkRedundantServiceInterface(@NotNull DomElementAnnotationHolder holder, Extension extension) {
|
||||
GenericAttributeValue<?> serviceInterface = DevKitDomUtil.getAttribute(extension, "serviceInterface");
|
||||
GenericAttributeValue<?> serviceImplementation = DevKitDomUtil.getAttribute(extension, "serviceImplementation");
|
||||
if (serviceInterface != null && serviceImplementation != null &&
|
||||
StringUtil.equals(serviceInterface.getStringValue(), serviceImplementation.getStringValue())) {
|
||||
if (hasMissingAttribute(extension, "testServiceImplementation")) {
|
||||
highlightRedundant(serviceInterface,
|
||||
DevKitBundle.message("inspections.plugin.xml.service.interface.class.redundant"),
|
||||
ProblemHighlightType.WARNING, holder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkPreloadUseProhibited(@NotNull DomElementAnnotationHolder holder, Extension extension) {
|
||||
GenericAttributeValue<?> preloadAttr = DevKitDomUtil.getAttribute(extension, "preload");
|
||||
GenericAttributeValue<?> serviceImplementation = DevKitDomUtil.getAttribute(extension, "serviceImplementation");
|
||||
if (preloadAttr != null
|
||||
&& preloadAttr.getStringValue() != null
|
||||
&& serviceImplementation != null
|
||||
&& serviceImplementation.getStringValue() != null
|
||||
&& !isServiceDeclaredInPlatform(holder.getFileElement().getOriginalFile())) {
|
||||
|
||||
var highlightType = servicePreloadingAllowListForNonCorePlugin.contains(serviceImplementation.getStringValue())
|
||||
? ProblemHighlightType.WARNING // existing known problems
|
||||
: ProblemHighlightType.GENERIC_ERROR; // new usages
|
||||
|
||||
highlightRedundant(preloadAttr, DevKitBundle.message("inspections.plugin.xml.service.preload.prohibited"), highlightType, holder);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isServiceDeclaredInPlatform(@NotNull XmlFile file) {
|
||||
var virtualFile = file.getVirtualFile();
|
||||
if (virtualFile == null) return false;
|
||||
|
||||
var project = file.getProject();
|
||||
if (!isIntelliJPlatformProject(project)) return false;
|
||||
|
||||
var roots = ProjectRootManager.getInstance(project).getContentRoots();
|
||||
for (VirtualFile root : roots) {
|
||||
VirtualFile communityPlatformDir = root.findFileByRelativePath("community/platform");
|
||||
VirtualFile platformDir = communityPlatformDir != null ? communityPlatformDir : root.findFileByRelativePath("platform");
|
||||
|
||||
if (platformDir != null) {
|
||||
return VfsUtilCore.isAncestor(platformDir, virtualFile, true);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void checkDefaultBundle(DomElement element, DomElementAnnotationHolder holder) {
|
||||
IdeaPlugin plugin = DomUtil.getParentOfType(element, IdeaPlugin.class, true);
|
||||
if (plugin != null && !DomUtil.hasXml(plugin.getResourceBundle())) {
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
<idea-plugin>
|
||||
<extensionPoints>
|
||||
<!--suppress PluginXmlValidity -->
|
||||
<extensionPoint name="applicationService" beanClass="com.intellij.openapi.components.ServiceDescriptor"/>
|
||||
</extensionPoints>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<applicationService <error descr="Plugins may not use preloading, use <postStartupActivity> ProjectActivity, lazy MessageBus topics or specific extensions instead.">preload="true"</error>
|
||||
serviceImplementation="java.lang.String"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
+4
@@ -86,6 +86,10 @@ public class PluginXmlExtensionRegistrationInspectionTest extends JavaCodeInsigh
|
||||
myFixture.testHighlighting("redundantServiceInterfaceClass.xml");
|
||||
}
|
||||
|
||||
public void testPreloadPreloadProhibitedService() {
|
||||
myFixture.testHighlighting("preloadProhibitedService.xml");
|
||||
}
|
||||
|
||||
public void testIntentionActionDescriptionDirectoryName() {
|
||||
myFixture.addClass("public class MyIntentionAction {}");
|
||||
myFixture.testHighlighting("intentionActionDescriptionDirectoryName.xml");
|
||||
|
||||
Reference in New Issue
Block a user