DBE-22829 DBE-22828 Add UI for plugin loaders

Merge-request: IJ-MR-156825
Merged-by: Ilia Epelbaum <ilia.epelbaum@jetbrains.com>

GitOrigin-RevId: bee18331d1ba03b4853efd655d4b03940ce99fae
This commit is contained in:
Ilia Epelbaum
2025-04-08 17:56:56 +00:00
committed by intellij-monorepo-bot
parent 867f7fcf0e
commit aa81d21bc3
7 changed files with 68 additions and 20 deletions
@@ -41,8 +41,11 @@ action.Console.TableResult.DeleteRows.text=Delete Selected Rows
action.Console.TableResult.DeleteRows.description=Delete selected rows
action.Console.TableResult.LoadFile.text=Load File\u2026
notification.title.no.script.engine.found.for.file.extension=No script engine found for file extension ''{0}''
notification.plugin.suggestion=Plugin suggestion
notification.please.install.js.script.engine=Please install plugin ''{0}''
notification.install.plugin=Install plugin
notification.install.plugin.with.name=Install plugin ''{0}''
notification.install.plugin.no=No
notification.content.please.make.sure.your.script.engine.jar.s.language.runtime.are.in.ide.classpath=Please, make sure your script engine jar(s) and language runtime are in the IDE classpath.
notification.title.failed.to.load.script=Failed to load script: {0}
excel.xlsx=Excel (xlsx)
@@ -396,4 +399,5 @@ action.Console.TableResult.SaveLobAsAction.TableChanged.text=table has been chan
action.Console.TableResult.SaveLobAsAction.AmbiguousQueryResult.text=ambiguous query result ({0} rows received)
action.Console.TableResult.LoadFullCellAction.Confirmation.title=Warning
action.Console.TableResult.LoadFullCellAction.Confirmation.text=One of the loaded cells contains a large amount of data, which may affect performance. Do you want to continue?
data.loaders.waiting=Waiting for the loaders to be ready
data.loaders.plugin.ad.notification=Get loader for the file ''{0}''
@@ -2,6 +2,7 @@ package com.intellij.database.extensions;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.extensions.PluginId;
import kotlinx.coroutines.Job;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -14,6 +15,10 @@ public class ExtensionsService {
return ApplicationManager.getApplication().getService(ExtensionsService.class);
}
public @NotNull Job unpackPluginResources(PluginId id) {
return null;
}
public @NotNull Predicate<Path> extensionsRootTypeRegularFileFilter() {
return null;
}
@@ -2,6 +2,7 @@ package com.intellij.database.extensions;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.util.text.StringUtil;
import kotlinx.coroutines.Job;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -25,6 +26,10 @@ public final class LoaderScripts {
private LoaderScripts() {
}
public static Job unpackPluginResources() {
return ExtensionsService.getInstance().unpackPluginResources(getPluginId());
}
public static @Nullable String getScriptsDirectoryWithoutUnpack() {
PluginId id = getPluginId();
return id == null ? null : ExtensionsService.getInstance().extensionsRootTypePathWithoutUnpack(id, SCRIPT_DIR);
@@ -4,6 +4,7 @@ import com.intellij.ide.extensionResources.ExtensionsRootType;
import com.intellij.ide.scratch.ScratchFileService;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.util.text.Strings;
import kotlinx.coroutines.Job;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -12,6 +13,11 @@ import java.nio.file.Path;
import java.util.function.Predicate;
final class ExtensionsServiceImpl extends ExtensionsService {
@Override
public @NotNull Job unpackPluginResources(PluginId id) {
return ExtensionsRootType.getInstance().updateBundledResources(id);
}
@Override
public @Nullable Path extensionsRootTypeFindResource(PluginId id, String path) throws IOException {
return ExtensionsRootType.getInstance().findResource(id, path);
+1 -1
View File
@@ -9295,7 +9295,7 @@ f:com.intellij.ide.extensionResources.ExtensionsRootType
- getOwner(com.intellij.openapi.vfs.VirtualFile):com.intellij.openapi.extensions.PluginId
- s:regularFileFilter():java.util.function.Predicate
- substituteName(com.intellij.openapi.project.Project,com.intellij.openapi.vfs.VirtualFile):java.lang.String
- updateBundledResources(com.intellij.openapi.extensions.PluginId):V
- updateBundledResources(com.intellij.openapi.extensions.PluginId):kotlinx.coroutines.Job
- updatePluginResources(com.intellij.openapi.extensions.PluginId):V
f:com.intellij.ide.extensionResources.ExternalResourcesUnpackExtensionBean
- com.intellij.openapi.extensions.PluginAware
@@ -15,6 +15,9 @@ import com.intellij.openapi.vfs.*;
import com.intellij.util.PlatformUtils;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.io.DigestUtil;
import kotlinx.coroutines.CompletableJob;
import kotlinx.coroutines.Job;
import kotlinx.coroutines.JobKt;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -296,41 +299,66 @@ public final class ExtensionsRootType extends RootType {
FileUtil.rename(file, newName);
}
private final Set<IdeaPluginDescriptor> updatingResources = ConcurrentHashMap.newKeySet();
private final Map<IdeaPluginDescriptor, Job> updatingResources = new ConcurrentHashMap<>();
public void updateBundledResources(@NotNull PluginId pluginId) {
executeOnPooledIoThread(() -> {
updateBundledResourcesImpl(pluginId);
});
}
private void updateBundledResourcesImpl(@NotNull PluginId pluginId) {
public Job updateBundledResources(@NotNull PluginId pluginId) {
IdeaPluginDescriptor plugin = PluginManagerCore.getPlugin(pluginId);
if (plugin == null || updatingResources.contains(plugin) || !updatingResources.add(plugin)) {
return;
if (plugin == null) {
CompletableJob job = JobKt.Job(null);
job.complete();
return job;
}
try { // updating lock
for (ExternalResourcesUnpackExtensionBean pluginBean : ExternalResourcesUnpackExtensionBean.getPluginsBeUnpackedTo(pluginId)) {
updateBundledResourcesImpl(pluginBean.getPluginDescriptor().getPluginId());
return updatingResources.computeIfAbsent(plugin, (d) -> executeOnPooledIoThread(() -> {
try {
updateBundledResourcesImpl(d);
}
finally {
updatingResources.remove(d);
}
}));
}
private void updateBundledResourcesImpl(@NotNull IdeaPluginDescriptor plugin) {
for (ExternalResourcesUnpackExtensionBean pluginBean : ExternalResourcesUnpackExtensionBean.getPluginsBeUnpackedTo(plugin.getPluginId())) {
updateBundledResourcesWithLock(pluginBean.getPluginDescriptor().getPluginId());
}
try {
ResourceVersions versions = ResourceVersions.getInstance();
if (versions.shouldUpdateResourcesOf(plugin)) {
extractBundledResources(pluginId, "");
extractBundledResources(plugin.getPluginId(), "");
versions.resourcesUpdated(plugin);
}
}
catch (IOException e) {
LOG.warn("Failed to extract bundled resources for plugin: " + plugin.getName(), e);
}
}
private void updateBundledResourcesWithLock(PluginId pluginId) {
IdeaPluginDescriptor ideaDesc = PluginManagerCore.getPlugin(pluginId);
if (ideaDesc == null || updatingResources.containsKey(ideaDesc)) {
return;
}
CompletableJob job = JobKt.Job(null);
if (updatingResources.putIfAbsent(ideaDesc, job) != null) {
job.complete();
return;
}
try { // updating lock
updateBundledResourcesImpl(ideaDesc);
}
finally {
updatingResources.remove(plugin);
updatingResources.remove(ideaDesc);
job.complete();
}
}
@TestOnly
public void updatePluginResources(@NotNull PluginId pluginId) {
updateBundledResourcesImpl(pluginId);
updateBundledResourcesWithLock(pluginId);
}
}
@@ -26,8 +26,8 @@ import kotlin.Throws
*/
@Internal
@ApiStatus.Obsolete
fun executeOnPooledIoThread(task: Runnable) {
(ApplicationManager.getApplication() as ComponentManagerEx).getCoroutineScope().launch(Dispatchers.IO) {
fun executeOnPooledIoThread(task: Runnable): Job {
return (ApplicationManager.getApplication() as ComponentManagerEx).getCoroutineScope().launch(Dispatchers.IO) {
task.run()
}
}