From ba30652e5258080137b155fc6e793742834951fe Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 5 Jun 2026 10:16:04 +0200 Subject: [PATCH] IJPL-246446 wire JCEF content modules into products Update product and plugin descriptors to include the new JCEF content modules wherever the corresponding browser-backed functionality remains available. This commit also carries the generated module-set snapshots, Bazel file lists, build property updates, and project-structure expectations produced by the module split. IJ-MR-184958 IJ-MR-184993 IJ-MR-179029 IJ-MR-184126 IJ-MR-181153 IJ-MR-146078 IJ-MR-175479 IJ-MR-186058 IJ-MR-193195 IJ-MR-196957 IJ-MR-199124 IJ-MR-197441 IJ-MR-204135 IJ-MR-204674 GitOrigin-RevId: d906efc7d3f058a8376e8cb39174491312557f65 --- .idea/modules.xml | 4 + build/bazel-generated-file-list.txt | 4 + images/BUILD.bazel | 2 + images/intellij.platform.images.iml | 1 + images/resources/META-INF/plugin.xml | 5 + .../plugin/intellij.libraries.jcef.plugin.iml | 2 +- .../ProductModuleSetValidatorTest.kt | 270 +++++++++--------- .../productLayout/CommunityModuleSets.kt | 4 + platform/new-ui-onboarding/jcef/api-dump.txt | 0 ...llij.platform.ide.newUiOnboarding.jcef.iml | 18 +- .../platform-impl/api-dump-unreviewed.txt | 1 - platform/platform-impl/api-dump.txt | 17 ++ .../internal/jcef/intellij.internal.jcef.iml | 2 +- .../detailed/handler/ContextMenuHandler.java | 19 -- platform/platform-impl/jcef/BUILD.bazel | 2 - platform/platform-impl/jcef/api-dump.txt | 17 ++ .../jcef/intellij.platform.ide.impl.jcef.iml | 19 +- .../intellij.platform.ide.impl.jcef.xml | 1 - .../platform-impl/update-checker/api-dump.txt | 4 + .../META-INF/intellij.moduleSets.core.ide.xml | 1 - .../intellij.moduleSets.core.lang.xml | 1 - .../intellij.moduleSets.essential.minimal.xml | 1 - .../intellij.moduleSets.essential.xml | 1 - .../intellij.moduleSets.ide.common.xml | 4 +- .../intellij.moduleSets.libraries.ide.xml | 1 - .../src/META-INF/PlatformExtensionPoints.xml | 5 - .../src/META-INF/PlatformExtensions.xml | 4 - .../serviceContainer/ComponentManagerImpl.kt | 3 + platform/ui.jcef/api-dump-unreviewed.txt | 10 - platform/ui.jcef/api-dump.txt | 6 + .../ui.jcef/jcef/JcefHwFacadeProvider.java | 2 + .../resources/intellij.platform.ui.jcef.xml | 9 + .../core/resources/META-INF/plugin.xml | 2 + .../core/resources/intellij.markdown.xml | 2 + plugins/markdown/test/BUILD.bazel | 2 + .../markdown/test/intellij.markdown.tests.iml | 1 + ...tellij.performanceTesting.remoteDriver.xml | 4 + .../resources/META-INF/plugin.xml | 1 + plugins/sh/core/BUILD.bazel | 2 + plugins/sh/core/intellij.sh.tests.iml | 1 + plugins/webp/BUILD.bazel | 2 + plugins/webp/intellij.webp.iml | 1 + plugins/webp/resources/META-INF/plugin.xml | 8 +- .../intellij.python.community.impl.xml | 2 + .../intellij.restructuredtext.python.xml | 4 + 45 files changed, 249 insertions(+), 223 deletions(-) create mode 100644 platform/new-ui-onboarding/jcef/api-dump.txt create mode 100644 platform/platform-impl/jcef/api-dump.txt diff --git a/.idea/modules.xml b/.idea/modules.xml index 687811dff4d7..8c80321ba9ef 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -617,6 +617,7 @@ + @@ -1061,6 +1062,7 @@ + @@ -1420,11 +1422,13 @@ + + diff --git a/build/bazel-generated-file-list.txt b/build/bazel-generated-file-list.txt index e373a93213d4..3719823cddc8 100644 --- a/build/bazel-generated-file-list.txt +++ b/build/bazel-generated-file-list.txt @@ -444,6 +444,7 @@ libraries/javax/annotation libraries/jaxen libraries/jbr libraries/jcef +libraries/jcef/plugin libraries/jcip libraries/jediterm-core libraries/jediterm-ui @@ -750,6 +751,7 @@ platform/navbar/plugin platform/navbar/shared platform/navbar/testFramework platform/new-ui-onboarding +platform/new-ui-onboarding/jcef platform/new-users-onboarding platform/non-modal-welcome-screen platform/non-modal-welcome-screen/backend @@ -768,6 +770,8 @@ platform/platform-impl/designer platform/platform-impl/eel platform/platform-impl/initial-config-import platform/platform-impl/internal +platform/platform-impl/internal/jcef +platform/platform-impl/jcef platform/platform-impl/recentProjects platform/platform-impl/remote platform/platform-impl/rpc diff --git a/images/BUILD.bazel b/images/BUILD.bazel index 8ce8a574acd2..a6ce147c3449 100644 --- a/images/BUILD.bazel +++ b/images/BUILD.bazel @@ -37,6 +37,7 @@ jvm_library( "//platform/ide-core", "//platform/util/jdom", "//libraries/jcef", + "//libraries/jcef/plugin", "//libraries/kotlinx/serialization/core", "//libraries/kotlinx/serialization/json", "//platform/core-impl", @@ -82,6 +83,7 @@ jvm_library( "//platform/ide-core:ide-core_test_lib", "//platform/util/jdom:jdom_test_lib", "//libraries/jcef:jcef_test_lib", + "//libraries/jcef/plugin:plugin_test_lib", "//libraries/kotlinx/serialization/core:core_test_lib", "//libraries/kotlinx/serialization/json:json_test_lib", "//platform/core-impl:core-impl_test_lib", diff --git a/images/intellij.platform.images.iml b/images/intellij.platform.images.iml index e3ce8eb02813..5c49f28ac4d6 100644 --- a/images/intellij.platform.images.iml +++ b/images/intellij.platform.images.iml @@ -45,6 +45,7 @@ + diff --git a/images/resources/META-INF/plugin.xml b/images/resources/META-INF/plugin.xml index b73c95d11c2e..3776571891c3 100644 --- a/images/resources/META-INF/plugin.xml +++ b/images/resources/META-INF/plugin.xml @@ -10,6 +10,11 @@ + + + + + diff --git a/libraries/jcef/plugin/intellij.libraries.jcef.plugin.iml b/libraries/jcef/plugin/intellij.libraries.jcef.plugin.iml index f11f9ea27991..510e3ffb6679 100644 --- a/libraries/jcef/plugin/intellij.libraries.jcef.plugin.iml +++ b/libraries/jcef/plugin/intellij.libraries.jcef.plugin.iml @@ -8,4 +8,4 @@ - + \ No newline at end of file diff --git a/platform/build-scripts/product-dsl/testSrc/validator/ProductModuleSetValidatorTest.kt b/platform/build-scripts/product-dsl/testSrc/validator/ProductModuleSetValidatorTest.kt index 4052d1a9a133..8859a2d7bd82 100644 --- a/platform/build-scripts/product-dsl/testSrc/validator/ProductModuleSetValidatorTest.kt +++ b/platform/build-scripts/product-dsl/testSrc/validator/ProductModuleSetValidatorTest.kt @@ -6,6 +6,7 @@ import com.intellij.platform.pluginSystem.parser.impl.elements.ModuleLoadingRule import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.runBlocking import org.assertj.core.api.Assertions +import org.assertj.core.api.Assertions.assertThat import org.jetbrains.intellij.build.productLayout.TestFailureLogger import org.jetbrains.intellij.build.productLayout.dependency.pluginGraph import org.jetbrains.intellij.build.productLayout.dependency.runValidationRule @@ -29,49 +30,46 @@ class ProductModuleSetValidatorTest { @Test fun `reports duplicate modules across module sets`(): Unit = runBlocking(Dispatchers.Default) { val graph = pluginGraph { - product("IDEA") { - includesModuleSet("set1") - includesModuleSet("set2") - } - moduleSet("set1") { - module("module.duplicate") - } - moduleSet("set2") { - module("module.duplicate") - } + product("IDEA") { + includesModuleSet("set1") + includesModuleSet("set2") + } + moduleSet("set1") { + module("module.duplicate") + } + moduleSet("set2") { + module("module.duplicate") + } } val model = testGenerationModel(graph) val errors = runValidationRule(ProductModuleSetValidator, model) - Assertions.assertThat(errors).hasSize(1) - Assertions.assertThat(errors[0]).isInstanceOf(DuplicateModulesError::class.java) + assertThat(errors).hasSize(1) + assertThat(errors[0]).isInstanceOf(DuplicateModulesError::class.java) val error = errors[0] as DuplicateModulesError - Assertions.assertThat(error.duplicates.keys).containsExactly(ContentModuleName("module.duplicate")) + assertThat(error.duplicates.keys).containsExactly(ContentModuleName("module.duplicate")) } @Test fun `reports duplicate between module set and product content`(): Unit = runBlocking(Dispatchers.Default) { - // For this test, we need to add module.a as product content too - // The test DSL doesn't directly support this, so we verify duplicates within module sets val graphWithDup = pluginGraph { - product("IDEA") { - includesModuleSet("set1") - includesModuleSet("set2") - } - moduleSet("set1") { - module("module.a") - } - moduleSet("set2") { - module("module.a") // Same module in different set - } + product("IDEA") { + includesModuleSet("set1") + content("module.a") + } + moduleSet("set1") { + module("module.a") + } } val model = testGenerationModel(graphWithDup) val errors = runValidationRule(ProductModuleSetValidator, model) - Assertions.assertThat(errors).hasSize(1) - Assertions.assertThat(errors[0]).isInstanceOf(DuplicateModulesError::class.java) + assertThat(errors).hasSize(1) + assertThat(errors[0]).isInstanceOf(DuplicateModulesError::class.java) + val error = errors[0] as DuplicateModulesError + assertThat(error.duplicates.keys).containsExactly(ContentModuleName("module.a")) } } @@ -81,146 +79,146 @@ class ProductModuleSetValidatorTest { fun `reports missing transitive dependency for critical module`(): Unit = runBlocking(Dispatchers.Default) { // module.a (EMBEDDED) -> dep.module -> missing.module val graph = pluginGraph { - product("IDEA") { - includesModuleSet("core") - } - moduleSet("core") { - moduleWithDeps("module.a", ModuleLoadingRuleValue.EMBEDDED, "dep.module") - } - // Set up content module dependencies (Module -> Module edges) - linkContentModuleDeps("module.a", "dep.module") - linkContentModuleDeps("dep.module", "missing.module") - // missing.module vertex created but not available in product + product("IDEA") { + includesModuleSet("core") + } + moduleSet("core") { + moduleWithDeps("module.a", ModuleLoadingRuleValue.EMBEDDED, "dep.module") + } + // Set up content module dependencies (Module -> Module edges) + linkContentModuleDeps("module.a", "dep.module") + linkContentModuleDeps("dep.module", "missing.module") + // missing.module vertex created but not available in product } val model = testGenerationModel(graph) val errors = runValidationRule(ProductModuleSetValidator, model) - Assertions.assertThat(errors).hasSize(1) - Assertions.assertThat(errors[0]).isInstanceOf(MissingDependenciesError::class.java) + assertThat(errors).hasSize(1) + assertThat(errors[0]).isInstanceOf(MissingDependenciesError::class.java) val error = errors[0] as MissingDependenciesError - Assertions.assertThat(error.missingModules.keys).contains(ContentModuleName("missing.module")) + assertThat(error.missingModules.keys).contains(ContentModuleName("missing.module")) } @Test fun `no error when dependency is available in module set`(): Unit = runBlocking(Dispatchers.Default) { // module.a -> module.b (both in same module set) val graph = pluginGraph { - product("IDEA") { - includesModuleSet("core") - } - moduleSet("core") { - moduleWithDeps("module.a", ModuleLoadingRuleValue.REQUIRED, "module.b") - module("module.b") - } - // Set up content module dependencies - linkContentModuleDeps("module.a", "module.b") + product("IDEA") { + includesModuleSet("core") + } + moduleSet("core") { + moduleWithDeps("module.a", ModuleLoadingRuleValue.REQUIRED, "module.b") + module("module.b") + } + // Set up content module dependencies + linkContentModuleDeps("module.a", "module.b") } val model = testGenerationModel(graph) val errors = runValidationRule(ProductModuleSetValidator, model) - Assertions.assertThat(errors).isEmpty() + assertThat(errors).isEmpty() } @Test fun `no error when dependency is in bundled plugin`(): Unit = runBlocking(Dispatchers.Default) { // module.a -> plugin.module (available via bundled plugin) val graph = pluginGraph { - product("IDEA") { - bundlesPlugin("my.plugin") - includesModuleSet("core") - } - plugin("my.plugin") { - content("plugin.module", loading = ModuleLoadingRuleValue.OPTIONAL) - } - moduleSet("core") { - moduleWithDeps("module.a", ModuleLoadingRuleValue.REQUIRED, "plugin.module") - } - // Set up content module dependencies - linkContentModuleDeps("module.a", "plugin.module") + product("IDEA") { + bundlesPlugin("my.plugin") + includesModuleSet("core") + } + plugin("my.plugin") { + content("plugin.module", loading = ModuleLoadingRuleValue.OPTIONAL) + } + moduleSet("core") { + moduleWithDeps("module.a", ModuleLoadingRuleValue.REQUIRED, "plugin.module") + } + // Set up content module dependencies + linkContentModuleDeps("module.a", "plugin.module") } val model = testGenerationModel(graph) val errors = runValidationRule(ProductModuleSetValidator, model) - Assertions.assertThat(errors).isEmpty() + assertThat(errors).isEmpty() } @Test fun `no error when product content dependency is in bundled plugin`(): Unit = runBlocking(Dispatchers.Default) { val graph = pluginGraph { - product("IDEA") { - bundlesPlugin("my.plugin") - content("product.module", ModuleLoadingRuleValue.REQUIRED) - } - plugin("my.plugin") { - content("plugin.module", loading = ModuleLoadingRuleValue.OPTIONAL) - } - linkContentModuleDeps("product.module", "plugin.module") + product("IDEA") { + bundlesPlugin("my.plugin") + content("product.module", ModuleLoadingRuleValue.REQUIRED) + } + plugin("my.plugin") { + content("plugin.module", loading = ModuleLoadingRuleValue.OPTIONAL) + } + linkContentModuleDeps("product.module", "plugin.module") } val model = testGenerationModel(graph) val errors = runValidationRule(ProductModuleSetValidator, model) - Assertions.assertThat(errors).isEmpty() + assertThat(errors).isEmpty() } @Test fun `no error for non-critical module with globally available dep`(): Unit = runBlocking(Dispatchers.Default) { // module.a (OPTIONAL) -> global.module (declared as content in another plugin, not bundled by IDEA) val graph = pluginGraph { - product("IDEA") { - includesModuleSet("core") - // Note: other.plugin is NOT bundled by IDEA - } - moduleSet("core") { - moduleWithDeps("module.a", ModuleLoadingRuleValue.OPTIONAL, "global.module") - } - // global.module exists as content in another plugin (not bundled by IDEA) - // This makes it "globally available" - it has a content source somewhere - plugin("other.plugin") { - content("global.module", loading = ModuleLoadingRuleValue.OPTIONAL) - } - // Set up content module dependencies - linkContentModuleDeps("module.a", "global.module") + product("IDEA") { + includesModuleSet("core") + // Note: other.plugin is NOT bundled by IDEA + } + moduleSet("core") { + moduleWithDeps("module.a", ModuleLoadingRuleValue.OPTIONAL, "global.module") + } + // global.module exists as content in another plugin (not bundled by IDEA) + // This makes it "globally available" - it has a content source somewhere + plugin("other.plugin") { + content("global.module", loading = ModuleLoadingRuleValue.OPTIONAL) + } + // Set up content module dependencies + linkContentModuleDeps("module.a", "global.module") } val model = testGenerationModel(graph) val errors = runValidationRule(ProductModuleSetValidator, model) - Assertions.assertThat(errors).isEmpty() + assertThat(errors).isEmpty() } @Test fun `respects allowedMissingDependencies`(): Unit = runBlocking(Dispatchers.Default) { val graph = pluginGraph { - product("IDEA") { - includesModuleSet("core") - allowsMissing("allowed.missing") - } - moduleSet("core") { - moduleWithDeps("module.a", ModuleLoadingRuleValue.EMBEDDED, "allowed.missing") - } - linkContentModuleDeps("module.a", "allowed.missing") + product("IDEA") { + includesModuleSet("core") + allowsMissing("allowed.missing") + } + moduleSet("core") { + moduleWithDeps("module.a", ModuleLoadingRuleValue.EMBEDDED, "allowed.missing") + } + linkContentModuleDeps("module.a", "allowed.missing") } val model = testGenerationModel(graph) val errors = runValidationRule(ProductModuleSetValidator, model) - Assertions.assertThat(errors).isEmpty() + assertThat(errors).isEmpty() } @Test fun `empty when no module sets`(): Unit = runBlocking(Dispatchers.Default) { val graph = pluginGraph { - product("IDEA") + product("IDEA") } val model = testGenerationModel(graph) val errors = runValidationRule(ProductModuleSetValidator, model) - Assertions.assertThat(errors).isEmpty() + assertThat(errors).isEmpty() } @Test @@ -228,75 +226,75 @@ class ProductModuleSetValidatorTest { // module.a has EMBEDDED loading in its module set - makes it critical // Dependencies of critical modules must be available in THIS product val graph = pluginGraph { - product("IDEA") { - includesModuleSet("core") - } - moduleSet("core") { - module("critical.module", ModuleLoadingRuleValue.EMBEDDED) // Critical - } - // missing.dep exists globally (has content source) but not in this product - // Critical modules can't rely on global availability - plugin("other.plugin") { - content("missing.dep", loading = ModuleLoadingRuleValue.OPTIONAL) - } - linkContentModuleDeps("critical.module", "missing.dep") + product("IDEA") { + includesModuleSet("core") + } + moduleSet("core") { + module("critical.module", ModuleLoadingRuleValue.EMBEDDED) // Critical + } + // missing.dep exists globally (has content source) but not in this product + // Critical modules can't rely on global availability + plugin("other.plugin") { + content("missing.dep", loading = ModuleLoadingRuleValue.OPTIONAL) + } + linkContentModuleDeps("critical.module", "missing.dep") } val model = testGenerationModel(graph) val errors = runValidationRule(ProductModuleSetValidator, model) // Error expected - missing.dep is not available in product and critical.module is critical - Assertions.assertThat(errors).hasSize(1) - Assertions.assertThat(errors[0]).isInstanceOf(MissingDependenciesError::class.java) + assertThat(errors).hasSize(1) + assertThat(errors[0]).isInstanceOf(MissingDependenciesError::class.java) val error = errors[0] as MissingDependenciesError - Assertions.assertThat(error.missingModules.keys).contains(ContentModuleName("missing.dep")) + assertThat(error.missingModules.keys).contains(ContentModuleName("missing.dep")) } @Test fun `dependency satisfied by module in another module set`(): Unit = runBlocking(Dispatchers.Default) { // module.a depends on dep.module, which is in set2 val graph = pluginGraph { - product("IDEA") { - includesModuleSet("set1") - includesModuleSet("set2") - } - moduleSet("set1") { - moduleWithDeps("module.a", ModuleLoadingRuleValue.EMBEDDED, "dep.module") - } - moduleSet("set2") { - module("dep.module", ModuleLoadingRuleValue.REQUIRED) - } - linkContentModuleDeps("module.a", "dep.module") + product("IDEA") { + includesModuleSet("set1") + includesModuleSet("set2") + } + moduleSet("set1") { + moduleWithDeps("module.a", ModuleLoadingRuleValue.EMBEDDED, "dep.module") + } + moduleSet("set2") { + module("dep.module", ModuleLoadingRuleValue.REQUIRED) + } + linkContentModuleDeps("module.a", "dep.module") } val model = testGenerationModel(graph) val errors = runValidationRule(ProductModuleSetValidator, model) // No error - dep.module is available in set2 - Assertions.assertThat(errors).isEmpty() + assertThat(errors).isEmpty() } @Test fun `module with transitive deps in same module set`(): Unit = runBlocking(Dispatchers.Default) { // module.a -> dep.a -> dep.b (transitive chain, all in same set) val graph = pluginGraph { - product("IDEA") { - includesModuleSet("core") - } - moduleSet("core") { - moduleWithDeps("module.a", ModuleLoadingRuleValue.REQUIRED, "dep.a") - moduleWithDeps("dep.a", ModuleLoadingRuleValue.OPTIONAL, "dep.b") - module("dep.b", ModuleLoadingRuleValue.OPTIONAL) - } - linkContentModuleDeps("module.a", "dep.a") - linkContentModuleDeps("dep.a", "dep.b") + product("IDEA") { + includesModuleSet("core") + } + moduleSet("core") { + moduleWithDeps("module.a", ModuleLoadingRuleValue.REQUIRED, "dep.a") + moduleWithDeps("dep.a", ModuleLoadingRuleValue.OPTIONAL, "dep.b") + module("dep.b", ModuleLoadingRuleValue.OPTIONAL) + } + linkContentModuleDeps("module.a", "dep.a") + linkContentModuleDeps("dep.a", "dep.b") } val model = testGenerationModel(graph) val errors = runValidationRule(ProductModuleSetValidator, model) // No errors - all transitive deps available in module set - Assertions.assertThat(errors).isEmpty() + assertThat(errors).isEmpty() } } } diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/productLayout/CommunityModuleSets.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/productLayout/CommunityModuleSets.kt index 1fedb2b3f269..cebe6c8eacd6 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/productLayout/CommunityModuleSets.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/productLayout/CommunityModuleSets.kt @@ -371,6 +371,10 @@ object CommunityModuleSets { moduleSet(essential()) moduleSet(compose()) + module("intellij.platform.ui.jcef") + module("intellij.platform.ide.newUiOnboarding.jcef") + module("intellij.platform.ide.impl.jcef") + // Additional IDE-specific modules module("intellij.platform.lvcs.impl") module("intellij.platform.collaborationTools") diff --git a/platform/new-ui-onboarding/jcef/api-dump.txt b/platform/new-ui-onboarding/jcef/api-dump.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/new-ui-onboarding/jcef/intellij.platform.ide.newUiOnboarding.jcef.iml b/platform/new-ui-onboarding/jcef/intellij.platform.ide.newUiOnboarding.jcef.iml index 78486d9dd6aa..e69b7b458f30 100644 --- a/platform/new-ui-onboarding/jcef/intellij.platform.ide.newUiOnboarding.jcef.iml +++ b/platform/new-ui-onboarding/jcef/intellij.platform.ide.newUiOnboarding.jcef.iml @@ -1,21 +1,5 @@ - - - - - - - - - - - - - - - @@ -32,4 +16,4 @@ - + \ No newline at end of file diff --git a/platform/platform-impl/api-dump-unreviewed.txt b/platform/platform-impl/api-dump-unreviewed.txt index 72df887e7f63..41f5efd22ce0 100644 --- a/platform/platform-impl/api-dump-unreviewed.txt +++ b/platform/platform-impl/api-dump-unreviewed.txt @@ -9723,7 +9723,6 @@ f:com.intellij.ui.BalloonImpl - wasFadedIn():Z - wasFadedOut():Z c:com.intellij.ui.BalloonImpl$ActionButton -- com.intellij.ui.jcef.HwFacadeNonOpaquePanel - com.intellij.openapi.wm.IdeGlassPane$TopComponent - pf:myButton:com.intellij.util.ui.BaseButtonBehavior - (com.intellij.ui.BalloonImpl,javax.swing.Icon,javax.swing.Icon,java.lang.String,com.intellij.util.Consumer):V diff --git a/platform/platform-impl/api-dump.txt b/platform/platform-impl/api-dump.txt index 84c5f6e23248..e4cd27c68e70 100644 --- a/platform/platform-impl/api-dump.txt +++ b/platform/platform-impl/api-dump.txt @@ -492,6 +492,17 @@ f:com.intellij.ide.browsers.WebBrowserManager - getFirstBrowser(com.intellij.ide.browsers.BrowserFamily):com.intellij.ide.browsers.WebBrowser - isActive(com.intellij.ide.browsers.WebBrowser):Z - loadState(org.jdom.Element):V +f:com.intellij.ide.browsers.actions.BaseOpenInBrowserAction +- com.intellij.openapi.project.DumbAwareAction +- (com.intellij.ide.browsers.WebBrowser):V +- actionPerformed(com.intellij.openapi.actionSystem.AnActionEvent):V +- getActionUpdateThread():com.intellij.openapi.actionSystem.ActionUpdateThread +- update(com.intellij.openapi.actionSystem.AnActionEvent):V +f:com.intellij.ide.browsers.actions.BaseOpenInBrowserAction$Handler +- sf:INSTANCE:com.intellij.ide.browsers.actions.BaseOpenInBrowserAction$Handler +- sf:doUpdate(com.intellij.openapi.actionSystem.AnActionEvent):com.intellij.ide.browsers.OpenInBrowserRequest +f:com.intellij.ide.browsers.actions.BaseOpenInBrowserActionKt +- sf:chooseUrl(java.util.Collection):org.jetbrains.concurrency.Promise f:com.intellij.ide.dnd.FileCopyPasteUtil - s:getFileList(java.awt.datatransfer.Transferable):java.util.List - s:getFileListFromAttachedObject(java.lang.Object):java.util.List @@ -1733,6 +1744,8 @@ f:com.intellij.openapi.fileEditor.impl.HTMLEditorProvider$Companion com.intellij.openapi.fileEditor.impl.HTMLEditorProvider$JsQueryHandler - a:query(J,java.lang.String,kotlin.coroutines.Continuation):java.lang.Object f:com.intellij.openapi.fileEditor.impl.HTMLEditorProvider$Request +- f:html:java.lang.String +- f:url:java.lang.String - f:withQueryHandler(com.intellij.openapi.fileEditor.impl.HTMLEditorProvider$JsQueryHandler):com.intellij.openapi.fileEditor.impl.HTMLEditorProvider$Request f:com.intellij.openapi.fileEditor.impl.HTMLEditorProvider$Request$Companion - f:html(java.lang.String):com.intellij.openapi.fileEditor.impl.HTMLEditorProvider$Request @@ -2442,6 +2455,8 @@ a:com.intellij.ui.AppIcon f:com.intellij.ui.AppUIUtil - sf:invokeOnEdt(java.lang.Runnable):V - sf:saveConsents(java.util.List):V +f:com.intellij.ui.AppUIUtilKt +- sf:loadSmallApplicationIcon(com.intellij.ui.scale.ScaleContext,I,Z):javax.swing.Icon f:com.intellij.ui.BadgeIconSupplier - (javax.swing.Icon):V - f:getInfoIcon(Z):javax.swing.Icon @@ -2456,6 +2471,8 @@ f:com.intellij.ui.BalloonImpl - setShowPointer(Z):V - startFadeoutTimer(I):V - startSmartFadeoutTimer(I):V +c:com.intellij.ui.BalloonImpl$ActionButton +- com.intellij.ui.components.panels.NonOpaquePanel com.intellij.ui.BalloonImpl$ActionProvider - a:createActions():java.util.List - a:layout(java.awt.Rectangle):V diff --git a/platform/platform-impl/internal/jcef/intellij.internal.jcef.iml b/platform/platform-impl/internal/jcef/intellij.internal.jcef.iml index 61046d7d8589..37d61fb003e6 100644 --- a/platform/platform-impl/internal/jcef/intellij.internal.jcef.iml +++ b/platform/platform-impl/internal/jcef/intellij.internal.jcef.iml @@ -81,4 +81,4 @@ - + \ No newline at end of file diff --git a/platform/platform-impl/internal/jcef/src/com/intellij/internal/jcef/test/detailed/handler/ContextMenuHandler.java b/platform/platform-impl/internal/jcef/src/com/intellij/internal/jcef/test/detailed/handler/ContextMenuHandler.java index d20ea203b626..aed30ff164a9 100644 --- a/platform/platform-impl/internal/jcef/src/com/intellij/internal/jcef/test/detailed/handler/ContextMenuHandler.java +++ b/platform/platform-impl/internal/jcef/src/com/intellij/internal/jcef/test/detailed/handler/ContextMenuHandler.java @@ -46,25 +46,6 @@ public class ContextMenuHandler extends CefContextMenuHandlerAdapter { model.addItem(MenuId.MENU_ID_NO_SPELLING_SUGGESTIONS, "Suggestions isn't implemented yet."); model.setEnabled(MenuId.MENU_ID_NO_SPELLING_SUGGESTIONS, false); - - //NOTE: uncomment to support DictionarySuggestions - //Vector suggestions = new Vector<>(); - //params.getDictionarySuggestions(suggestions); - // - //// Spell checking menu - //model.addSeparator(); - //if (suggestions.isEmpty()) { - // model.addItem(MenuId.MENU_ID_NO_SPELLING_SUGGESTIONS, "No suggestions"); - // model.setEnabled(MenuId.MENU_ID_NO_SPELLING_SUGGESTIONS, false); - // return; - //} - // - //int id = MenuId.MENU_ID_SPELLCHECK_SUGGESTION_0; - //for (String suggestedWord : suggestions) { - // model.addItem(id, suggestedWord); - // suggestions_.put(id, suggestedWord); - // if (++id > MenuId.MENU_ID_SPELLCHECK_SUGGESTION_LAST) break; - //} } @Override diff --git a/platform/platform-impl/jcef/BUILD.bazel b/platform/platform-impl/jcef/BUILD.bazel index 82e575b8a94e..e84f63a8cabf 100644 --- a/platform/platform-impl/jcef/BUILD.bazel +++ b/platform/platform-impl/jcef/BUILD.bazel @@ -24,7 +24,6 @@ jvm_library( "//libraries/jcef", "//platform/core-impl", "//platform/platform-impl:ide-impl", - "//platform/platform-frontend:frontend", "//platform/ui.jcef", "//platform/analysis-api:analysis", "//platform/built-in-server-api:builtInServer", @@ -61,7 +60,6 @@ jvm_library( "//libraries/jcef:jcef_test_lib", "//platform/core-impl:core-impl_test_lib", "//platform/platform-impl:ide-impl_test_lib", - "//platform/platform-frontend:frontend_test_lib", "//platform/ui.jcef:ui.jcef_test_lib", "//platform/analysis-api:analysis_test_lib", "//platform/built-in-server-api:builtInServer_test_lib", diff --git a/platform/platform-impl/jcef/api-dump.txt b/platform/platform-impl/jcef/api-dump.txt new file mode 100644 index 000000000000..ff8c168531a5 --- /dev/null +++ b/platform/platform-impl/jcef/api-dump.txt @@ -0,0 +1,17 @@ +f:com.intellij.ide.actions.JcefWhatsNewPageProvider +- ():V +- isAvailable():Z +- openWhatsNewPage(com.intellij.openapi.project.Project,java.lang.String,Z,com.intellij.openapi.fileEditor.impl.HTMLEditorProvider$JsQueryHandler):V +f:com.intellij.ide.browsers.actions.OpenHtmlInEmbeddedBrowserAction +- com.intellij.openapi.project.DumbAwareAction +- ():V +- actionPerformed(com.intellij.openapi.actionSystem.AnActionEvent):V +- getActionUpdateThread():com.intellij.openapi.actionSystem.ActionUpdateThread +- update(com.intellij.openapi.actionSystem.AnActionEvent):V +f:com.intellij.internal.BrowseWebAction +- com.intellij.openapi.actionSystem.AnAction +- com.intellij.openapi.project.DumbAware +- ():V +- actionPerformed(com.intellij.openapi.actionSystem.AnActionEvent):V +- getActionUpdateThread():com.intellij.openapi.actionSystem.ActionUpdateThread +- update(com.intellij.openapi.actionSystem.AnActionEvent):V diff --git a/platform/platform-impl/jcef/intellij.platform.ide.impl.jcef.iml b/platform/platform-impl/jcef/intellij.platform.ide.impl.jcef.iml index ebff1384c2aa..17e80730fb10 100644 --- a/platform/platform-impl/jcef/intellij.platform.ide.impl.jcef.iml +++ b/platform/platform-impl/jcef/intellij.platform.ide.impl.jcef.iml @@ -1,21 +1,5 @@ - - - - - - - - - - - - - - - @@ -28,7 +12,6 @@ - @@ -48,4 +31,4 @@ - + \ No newline at end of file diff --git a/platform/platform-impl/jcef/resources/intellij.platform.ide.impl.jcef.xml b/platform/platform-impl/jcef/resources/intellij.platform.ide.impl.jcef.xml index 3da1df02f5f1..7d1cad43fdbb 100644 --- a/platform/platform-impl/jcef/resources/intellij.platform.ide.impl.jcef.xml +++ b/platform/platform-impl/jcef/resources/intellij.platform.ide.impl.jcef.xml @@ -8,7 +8,6 @@ - diff --git a/platform/platform-impl/update-checker/api-dump.txt b/platform/platform-impl/update-checker/api-dump.txt index 469726effda3..8025fea7b3cf 100644 --- a/platform/platform-impl/update-checker/api-dump.txt +++ b/platform/platform-impl/update-checker/api-dump.txt @@ -1,3 +1,7 @@ +f:com.intellij.openapi.updateSettings.impl.IdeUpdateUsageTriggerCollector +- ():V +- getGroup():com.intellij.internal.statistic.eventLog.EventLogGroup +- s:majorUpdateHappened(Z):V f:com.intellij.openapi.updateSettings.impl.PluginUpdateFacadeKt - sf:getPendingUpdates():java.util.Collection - sf:installUpdates(java.util.Collection,javax.swing.JComponent,java.util.function.Consumer):V diff --git a/platform/platform-resources/generated/META-INF/intellij.moduleSets.core.ide.xml b/platform/platform-resources/generated/META-INF/intellij.moduleSets.core.ide.xml index 2e94bac57fc9..785be024f4d1 100644 --- a/platform/platform-resources/generated/META-INF/intellij.moduleSets.core.ide.xml +++ b/platform/platform-resources/generated/META-INF/intellij.moduleSets.core.ide.xml @@ -163,7 +163,6 @@ - diff --git a/platform/platform-resources/generated/META-INF/intellij.moduleSets.core.lang.xml b/platform/platform-resources/generated/META-INF/intellij.moduleSets.core.lang.xml index 87d7475edcc5..039760d602de 100644 --- a/platform/platform-resources/generated/META-INF/intellij.moduleSets.core.lang.xml +++ b/platform/platform-resources/generated/META-INF/intellij.moduleSets.core.lang.xml @@ -164,7 +164,6 @@ - diff --git a/platform/platform-resources/generated/META-INF/intellij.moduleSets.essential.minimal.xml b/platform/platform-resources/generated/META-INF/intellij.moduleSets.essential.minimal.xml index 4eb0f10dc376..0505506df0e6 100644 --- a/platform/platform-resources/generated/META-INF/intellij.moduleSets.essential.minimal.xml +++ b/platform/platform-resources/generated/META-INF/intellij.moduleSets.essential.minimal.xml @@ -165,7 +165,6 @@ - diff --git a/platform/platform-resources/generated/META-INF/intellij.moduleSets.essential.xml b/platform/platform-resources/generated/META-INF/intellij.moduleSets.essential.xml index e4279d82838a..46e74d07047e 100644 --- a/platform/platform-resources/generated/META-INF/intellij.moduleSets.essential.xml +++ b/platform/platform-resources/generated/META-INF/intellij.moduleSets.essential.xml @@ -166,7 +166,6 @@ - diff --git a/platform/platform-resources/generated/META-INF/intellij.moduleSets.ide.common.xml b/platform/platform-resources/generated/META-INF/intellij.moduleSets.ide.common.xml index 760cfbbfa2d0..fb5439e2b959 100644 --- a/platform/platform-resources/generated/META-INF/intellij.moduleSets.ide.common.xml +++ b/platform/platform-resources/generated/META-INF/intellij.moduleSets.ide.common.xml @@ -169,7 +169,6 @@ - @@ -391,6 +390,9 @@ + + + diff --git a/platform/platform-resources/generated/META-INF/intellij.moduleSets.libraries.ide.xml b/platform/platform-resources/generated/META-INF/intellij.moduleSets.libraries.ide.xml index 1969a34a226f..e3b45522152d 100644 --- a/platform/platform-resources/generated/META-INF/intellij.moduleSets.libraries.ide.xml +++ b/platform/platform-resources/generated/META-INF/intellij.moduleSets.libraries.ide.xml @@ -4,7 +4,6 @@ - diff --git a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml index 4d60d2e50f96..c62c63cb5984 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml @@ -537,7 +537,6 @@ - @@ -640,10 +639,6 @@ interface="com.intellij.ide.gdpr.ui.consents.AiDataCollectionExternalSettings" dynamic="true"/> - - - - diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml index 4b9a334bb470..080886f0352f 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml @@ -231,10 +231,6 @@ The refresh itself is toggled by (Preferences | Appearance & Behavior | Syst - - - - diff --git a/platform/service-container/src/com/intellij/serviceContainer/ComponentManagerImpl.kt b/platform/service-container/src/com/intellij/serviceContainer/ComponentManagerImpl.kt index c8f4d0e7b99c..c01f37e10f1b 100644 --- a/platform/service-container/src/com/intellij/serviceContainer/ComponentManagerImpl.kt +++ b/platform/service-container/src/com/intellij/serviceContainer/ComponentManagerImpl.kt @@ -1598,12 +1598,14 @@ val servicePreloadingAllowListForNonCorePlugin: Set = java.util.Set.of( "com.jetbrains.rider.protocol.RiderProtocolProjectSessionsManager", "com.jetbrains.rider.workspaceModel.RiderWorkspaceModel", "com.intellij.clouds.docker.gateway.host.DockerDevcontainerHostInitializer", + "com.intellij.ui.jcef.JBCefStartup", // Remote Development "com.intellij.cwm.plugin.driver.RemoteDriverHostService", "com.intellij.cwm.plugin.driver.RobotHostServiceImpl", "com.intellij.cwm.plugin.following.FollowMeManagerService", "com.intellij.cwm.plugin.following.GuestFollowMeManager", + "com.intellij.cwm.plugin.ui.BackendModalityHost", "com.intellij.cwm.plugin.ports.CwmPortForwardingToolWindowManager", "com.intellij.cwm.plugin.users.BackendUserManager", "com.intellij.platform.vcs.backend.split.BackendLocalChangesHost", @@ -1613,6 +1615,7 @@ val servicePreloadingAllowListForNonCorePlugin: Set = java.util.Set.of( "com.jetbrains.rdserver.daemon.BackendDaemonStatusHost", "com.jetbrains.rdserver.daemon.BackendHighlighterRegistrationsHost", "com.jetbrains.rdserver.daemon.inlays.BackendCodeVisionHost.Settings", + $$"com.jetbrains.rdserver.daemon.inlays.BackendCodeVisionHost$Settings", "com.jetbrains.rdserver.debugger.BackendBreakpointHost", "com.jetbrains.rdserver.debugger.BackendConsoleInfoHost", "com.jetbrains.rdserver.debugger.BackendDebuggerHost", diff --git a/platform/ui.jcef/api-dump-unreviewed.txt b/platform/ui.jcef/api-dump-unreviewed.txt index 80979203f5b6..6b2dde5507fd 100644 --- a/platform/ui.jcef/api-dump-unreviewed.txt +++ b/platform/ui.jcef/api-dump-unreviewed.txt @@ -1,19 +1,9 @@ c:com.intellij.ui.jcef.HwFacadeJPanel - javax.swing.JPanel - ():V -- addNotify():V -- hide():V -- paint(java.awt.Graphics):V -- removeNotify():V -- show():V c:com.intellij.ui.jcef.HwFacadeNonOpaquePanel - com.intellij.ui.components.panels.NonOpaquePanel - ():V -- addNotify():V -- hide():V -- paint(java.awt.Graphics):V -- removeNotify():V -- show():V f:com.intellij.ui.jcef.JBCefApp - createClient():com.intellij.ui.jcef.JBCefClient - getCefSettings():org.cef.CefSettings diff --git a/platform/ui.jcef/api-dump.txt b/platform/ui.jcef/api-dump.txt index cad9e67003e0..e0aff7de2626 100644 --- a/platform/ui.jcef/api-dump.txt +++ b/platform/ui.jcef/api-dump.txt @@ -52,5 +52,11 @@ f:com.intellij.ui.jcef.JBCefPsiNavigationUtils c:com.intellij.ui.jcef.JCEFHtmlPanel - (java.lang.String):V - setHtml(java.lang.String):V +f:com.intellij.ui.jcef.JcefFocusedComponentProvider +- ():V +- getFocusedComponent():java.awt.Component +f:com.intellij.ui.jcef.JcefProxySettingsListener +- ():V +- proxySettingsChanged():V c:com.intellij.ui.jcef.utils.JBCefStreamResourceHandler - org.cef.handler.CefResourceHandlerAdapter diff --git a/platform/ui.jcef/jcef/JcefHwFacadeProvider.java b/platform/ui.jcef/jcef/JcefHwFacadeProvider.java index acf2a9f6c53c..3a879ee05e79 100644 --- a/platform/ui.jcef/jcef/JcefHwFacadeProvider.java +++ b/platform/ui.jcef/jcef/JcefHwFacadeProvider.java @@ -2,12 +2,14 @@ package com.intellij.ui.jcef; import com.intellij.ui.HwFacadeProvider; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import javax.swing.JComponent; import java.awt.Graphics; import java.util.function.Consumer; +@ApiStatus.Internal public final class JcefHwFacadeProvider implements HwFacadeProvider { @Override public boolean isAvailable() { diff --git a/platform/ui.jcef/resources/intellij.platform.ui.jcef.xml b/platform/ui.jcef/resources/intellij.platform.ui.jcef.xml index 11ea80bb4138..946af860e171 100644 --- a/platform/ui.jcef/resources/intellij.platform.ui.jcef.xml +++ b/platform/ui.jcef/resources/intellij.platform.ui.jcef.xml @@ -17,7 +17,16 @@ + + + + + + + + + diff --git a/plugins/markdown/core/resources/META-INF/plugin.xml b/plugins/markdown/core/resources/META-INF/plugin.xml index 2d37debfaea1..85257036d001 100644 --- a/plugins/markdown/core/resources/META-INF/plugin.xml +++ b/plugins/markdown/core/resources/META-INF/plugin.xml @@ -8,7 +8,9 @@ + + diff --git a/plugins/markdown/core/resources/intellij.markdown.xml b/plugins/markdown/core/resources/intellij.markdown.xml index 867bc1ae9dc7..380fc2ae436f 100644 --- a/plugins/markdown/core/resources/intellij.markdown.xml +++ b/plugins/markdown/core/resources/intellij.markdown.xml @@ -1,7 +1,9 @@ + + diff --git a/plugins/markdown/test/BUILD.bazel b/plugins/markdown/test/BUILD.bazel index 81a0561a439c..3e16c95e4601 100644 --- a/plugins/markdown/test/BUILD.bazel +++ b/plugins/markdown/test/BUILD.bazel @@ -37,6 +37,7 @@ jvm_library( "//platform/platform-util-netty:ide-util-netty", "//libraries/jsoup", "//libraries/jcef", + "//libraries/jcef/plugin", "//platform/util-ex", "//libraries/markdown", "//plugins/toml", @@ -70,6 +71,7 @@ jvm_library( ":tests", "//platform/platform-util-netty:ide-util-netty_test_lib", "//platform/ide-core:ide-core_test_lib", + "//libraries/jcef/plugin:plugin_test_lib", "//platform/structure-view-impl/plugin:plugin_test_lib", ], deps = [ diff --git a/plugins/markdown/test/intellij.markdown.tests.iml b/plugins/markdown/test/intellij.markdown.tests.iml index 116bf139c1c1..6c027878a7a4 100644 --- a/plugins/markdown/test/intellij.markdown.tests.iml +++ b/plugins/markdown/test/intellij.markdown.tests.iml @@ -47,6 +47,7 @@ + diff --git a/plugins/performanceTesting/remote-driver/resources/intellij.performanceTesting.remoteDriver.xml b/plugins/performanceTesting/remote-driver/resources/intellij.performanceTesting.remoteDriver.xml index a24ff94f6054..84beed676d47 100644 --- a/plugins/performanceTesting/remote-driver/resources/intellij.performanceTesting.remoteDriver.xml +++ b/plugins/performanceTesting/remote-driver/resources/intellij.performanceTesting.remoteDriver.xml @@ -1,6 +1,10 @@ + + + + + diff --git a/plugins/sh/core/BUILD.bazel b/plugins/sh/core/BUILD.bazel index f84ae9b5f41d..2594f67224f6 100644 --- a/plugins/sh/core/BUILD.bazel +++ b/plugins/sh/core/BUILD.bazel @@ -118,6 +118,7 @@ jvm_library( "//plugins/sh/core", "//platform/structure-view-impl/plugin", "//libraries/misc/plugin", + "//libraries/jcef/plugin", "//plugins/sh/plugin:plugin-main", "//platform/analysis-impl", "//platform/lang-api:lang", @@ -150,6 +151,7 @@ jvm_library( ":tests", "//platform/structure-view-impl/plugin:plugin_test_lib", "//libraries/misc/plugin:plugin_test_lib", + "//libraries/jcef/plugin:plugin_test_lib", "//plugins/sh/plugin:plugin-main_test_lib", "//platform/ide-core:ide-core_test_lib", ], diff --git a/plugins/sh/core/intellij.sh.tests.iml b/plugins/sh/core/intellij.sh.tests.iml index 161f1894fc94..a5746e0a166c 100644 --- a/plugins/sh/core/intellij.sh.tests.iml +++ b/plugins/sh/core/intellij.sh.tests.iml @@ -20,6 +20,7 @@ + diff --git a/plugins/webp/BUILD.bazel b/plugins/webp/BUILD.bazel index 2f8a78b946a1..8734ec9cde38 100644 --- a/plugins/webp/BUILD.bazel +++ b/plugins/webp/BUILD.bazel @@ -25,6 +25,7 @@ jvm_library( "//platform/lang-api:lang", "//platform/platform-impl:ide-impl", "//platform/lang-impl", + "//images", "//plugins/webp/lib:webp-libwebp", ], ) @@ -45,6 +46,7 @@ jvm_library( "//platform/lang-api:lang_test_lib", "//platform/platform-impl:ide-impl_test_lib", "//platform/lang-impl:lang-impl_test_lib", + "//images:images_test_lib", ], ) ### auto-generated section `build intellij.webp` end diff --git a/plugins/webp/intellij.webp.iml b/plugins/webp/intellij.webp.iml index 9ceecfc2b663..0e1679e2657e 100644 --- a/plugins/webp/intellij.webp.iml +++ b/plugins/webp/intellij.webp.iml @@ -13,6 +13,7 @@ + diff --git a/plugins/webp/resources/META-INF/plugin.xml b/plugins/webp/resources/META-INF/plugin.xml index 408aa6e16f8d..1573aaae5100 100644 --- a/plugins/webp/resources/META-INF/plugin.xml +++ b/plugins/webp/resources/META-INF/plugin.xml @@ -1,11 +1,15 @@ intellij.webp JetBrains - com.intellij.modules.lang - WebP Support + WebP Allows viewing images in the WebP format in the IDE.

]]>
+ + + + + diff --git a/python/pluginResources/intellij.python.community.impl.xml b/python/pluginResources/intellij.python.community.impl.xml index 087c8f67e398..46c5e3fcaf1b 100644 --- a/python/pluginResources/intellij.python.community.impl.xml +++ b/python/pluginResources/intellij.python.community.impl.xml @@ -6,10 +6,12 @@ + + diff --git a/python/python-restructuredtext/resources/intellij.restructuredtext.python.xml b/python/python-restructuredtext/resources/intellij.restructuredtext.python.xml index d2a8b13750f5..4ac7b89e39b1 100644 --- a/python/python-restructuredtext/resources/intellij.restructuredtext.python.xml +++ b/python/python-restructuredtext/resources/intellij.restructuredtext.python.xml @@ -1,7 +1,11 @@ + + + +