diff --git a/platform/platform-api/intellij.platform.ide.iml b/platform/platform-api/intellij.platform.ide.iml
index ae734b9f1638..79f3ea6c7b12 100644
--- a/platform/platform-api/intellij.platform.ide.iml
+++ b/platform/platform-api/intellij.platform.ide.iml
@@ -32,7 +32,6 @@
-
\ No newline at end of file
diff --git a/platform/platform-api/src/com/intellij/ide/ui/UITheme.java b/platform/platform-api/src/com/intellij/ide/ui/UITheme.java
index 046c4da5f0af..0d8944ae703c 100644
--- a/platform/platform-api/src/com/intellij/ide/ui/UITheme.java
+++ b/platform/platform-api/src/com/intellij/ide/ui/UITheme.java
@@ -1,14 +1,13 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.ide.ui;
-import com.fasterxml.jackson.jr.ob.JSON;
+import com.fasterxml.jackson.core.JsonFactory;
import com.intellij.AbstractBundle;
import com.intellij.DynamicBundle;
import com.intellij.ide.plugins.cl.PluginAwareClassLoader;
import com.intellij.ide.ui.laf.UIThemeLookAndFeelInfo;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.IconPathPatcher;
-import com.intellij.openapi.util.SystemInfoRt;
import com.intellij.ui.ColorHexUtil;
import com.intellij.ui.Gray;
import com.intellij.ui.icons.ImageDataByPathLoader;
@@ -31,6 +30,7 @@ import java.awt.*;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
+import java.util.List;
import java.util.*;
import java.util.function.Function;
@@ -44,11 +44,6 @@ public final class UITheme {
private final UIThemeBean bean;
- private static final String OS_MACOS_KEY = "os.mac";
- private static final String OS_WINDOWS_KEY = "os.windows";
- private static final String OS_LINUX_KEY = "os.linux";
- private static final String OS_DEFAULT_KEY = "os.default";
-
private UITheme(@NotNull UIThemeBean bean) {
this.bean = bean;
}
@@ -73,18 +68,9 @@ public final class UITheme {
return bean.author;
}
- // it caches classes - must be not extracted to util class
- // .disable(JSON.Feature.PRESERVE_FIELD_ORDERING) - cannot be disabled, for unknown reason order is important,
- // for example, button label font color for light theme is not white, but black
- private static final JSON JSON_READER = JSON.builder()
- .enable(JSON.Feature.READ_ONLY)
- .disable(JSON.Feature.USE_DEFERRED_MAPS)
- .disable(JSON.Feature.HANDLE_JAVA_BEANS)
- .build();
-
@ApiStatus.Internal
public static @NotNull UITheme loadFromJson(@NotNull InputStream stream, @NotNull @NonNls String themeId) throws IOException {
- UIThemeBean theme = JSON_READER.beanFrom(UIThemeBean.class, stream);
+ UIThemeBean theme = UIThemeBean.Companion.readTheme(new JsonFactory().createParser(stream));
theme.id = themeId;
return postProcessTheme(theme, findParentTheme(theme), null, Function.identity());
}
@@ -93,7 +79,7 @@ public final class UITheme {
@NotNull @NonNls String themeId,
@Nullable ClassLoader provider,
@NotNull Function super String, String> iconsMapper) throws IOException {
- UIThemeBean theme = JSON_READER.beanFrom(UIThemeBean.class, data);
+ UIThemeBean theme = UIThemeBean.Companion.readTheme(new JsonFactory().createParser(data));
theme.id = themeId;
return postProcessTheme(theme, findParentTheme(theme), provider, iconsMapper);
}
@@ -105,7 +91,7 @@ public final class UITheme {
@NotNull Function super String, String> iconsMapper,
@Nullable UITheme defaultDarkParent,
@Nullable UITheme defaultLightParent) throws IOException {
- UIThemeBean theme = JSON_READER.beanFrom(UIThemeBean.class, data);
+ UIThemeBean theme = UIThemeBean.Companion.readTheme(new JsonFactory().createParser(data));
theme.id = themeId;
if (theme.dark && parentTheme == null) {
return postProcessTheme(theme, defaultDarkParent, provider, iconsMapper);
@@ -120,11 +106,9 @@ public final class UITheme {
@Nullable UITheme parentTheme,
@Nullable ClassLoader provider,
@NotNull Function super String, String> iconsMapper) throws IllegalStateException {
- normalizeKeyPaths(theme);
if (parentTheme != null) {
UIThemeBean.Companion.importFromParentTheme(theme, parentTheme.bean);
}
- UIThemeBean.Companion.putDefaultsIfAbsent(theme);
return new UITheme(loadFromJson(theme, provider, iconsMapper));
}
@@ -143,60 +127,6 @@ public final class UITheme {
return null;
}
- /**
- * Flatten
- *
{@code "Editor": { "SearchField" : { "borderInsets" : "7,10,7,8" } }}
- * to
- * {@code "Editor.SearchField.borderInsets" : "7,10,7,8"}
- * in internal representation.
- *
- * We also resolve per-OS keys here:
- *
{@code
- * "Menu.borderColor": {
- * "os.default": "Grey12",
- * "os.windows": "Blue12"
- * }
- * }
- *
- * This is helpful when we need to check if some key was already set in {@link UIThemeBean.Companion#putDefaultsIfAbsent},
- * and to make overriding parentTheme keys independent of used form.
- *
- * NB: we intentionally do not expand "*" patterns here.
- */
- private static void normalizeKeyPaths(@NotNull UIThemeBean theme) {
- if (theme.ui == null) {
- return;
- }
-
- Map result = new LinkedHashMap<>();
- for (Map.Entry entry : theme.ui.entrySet()) {
- normalizeKeyValue(entry.getKey(), entry.getValue(), result);
- }
- theme.ui = result;
- }
-
- private static void normalizeKeyValue(@NotNull String keyPrefix,
- @NotNull Object value,
- @NotNull Map result) {
- if (value instanceof Map) {
- @SuppressWarnings("unchecked") Map valueMap = (Map)value;
-
- Object osValue = getOSCustomization(valueMap);
- if (osValue == null) {
- for (Map.Entry entry : valueMap.entrySet()) {
- String uiKey = createUIKey(keyPrefix, entry.getKey());
- normalizeKeyValue(uiKey, entry.getValue(), result);
- }
- }
- else {
- normalizeKeyValue(keyPrefix, osValue, result);
- }
- }
- else {
- result.put(keyPrefix, value);
- }
- }
-
private static @NotNull UIThemeBean loadFromJson(@NotNull UIThemeBean theme,
@Nullable ClassLoader provider,
@NotNull Function super String, String> iconsMapper) throws IllegalStateException {
@@ -422,7 +352,7 @@ public final class UITheme {
return bean.editorScheme;
}
- public String @Nullable [] getAdditionalEditorSchemes() {
+ public @Nullable List getAdditionalEditorSchemes() {
return bean.additionalEditorSchemes;
}
@@ -530,18 +460,6 @@ public final class UITheme {
}
}
- private static @Nullable Object getOSCustomization(@NotNull Map map) {
- String osKey = SystemInfoRt.isWindows ? OS_WINDOWS_KEY :
- SystemInfoRt.isMac ? OS_MACOS_KEY :
- SystemInfoRt.isLinux ? OS_LINUX_KEY : null;
- if (osKey != null && map.containsKey(osKey)) {
- return map.get(osKey);
- }
- else {
- return map.get(OS_DEFAULT_KEY);
- }
- }
-
@SuppressWarnings("unchecked")
private static void addPattern(String key, Object value, UIDefaults defaults) {
Object o = defaults.get("*");
diff --git a/platform/platform-api/src/com/intellij/ide/ui/UIThemeBean.kt b/platform/platform-api/src/com/intellij/ide/ui/UIThemeBean.kt
index b2855f7ce032..4a5b4ce85e1c 100644
--- a/platform/platform-api/src/com/intellij/ide/ui/UIThemeBean.kt
+++ b/platform/platform-api/src/com/intellij/ide/ui/UIThemeBean.kt
@@ -1,35 +1,20 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
-@file:Suppress("ReplacePutWithAssignment")
+@file:Suppress("ReplacePutWithAssignment", "ReplaceGetOrSet")
package com.intellij.ide.ui
+import com.fasterxml.jackson.core.JsonParser
+import com.fasterxml.jackson.core.JsonToken
+import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.util.IconPathPatcher
-import com.intellij.ui.ExperimentalUI.Companion.isNewUI
+import com.intellij.openapi.util.SystemInfoRt
+import com.intellij.ui.ExperimentalUI
import com.intellij.util.SVGLoader.SvgElementColorPatcherProvider
+import java.util.*
+import java.util.function.BiFunction
internal class UIThemeBean {
companion object {
- /**
- * Ensure that the old themes are not missing some vital keys.
- *
- * We are patching them here instead of using [com.intellij.ui.JBColor.namedColor] fallback
- * to make sure [javax.swing.UIManager.getColor] works properly.
- */
- fun putDefaultsIfAbsent(theme: UIThemeBean) {
- var ui = theme.ui
- if (ui == null) {
- ui = LinkedHashMap()
- theme.ui = ui
- }
- if (isNewUI()) {
- ui.putIfAbsent("EditorTabs.underlineArc", "4")
-
- // require theme to specify ToolWindow stripe button colors explicitly, without "*"
- ui.putIfAbsent("ToolWindow.Button.selectedBackground", "#3573F0")
- ui.putIfAbsent("ToolWindow.Button.selectedForeground", "#FFFFFF")
- }
- }
-
fun importFromParentTheme(theme: UIThemeBean, parentTheme: UIThemeBean) {
theme.ui = importMapFromParentTheme(theme.ui, parentTheme.ui)
theme.icons = importMapFromParentTheme(theme.icons, parentTheme.icons)
@@ -39,7 +24,8 @@ internal class UIThemeBean {
theme.iconColorsOnSelection = importMapFromParentTheme(theme.iconColorsOnSelection, parentTheme.iconColorsOnSelection)
}
- private fun importMapFromParentTheme(themeMap: MutableMap?, parentThemeMap: Map?): MutableMap? {
+ private fun importMapFromParentTheme(themeMap: MutableMap?,
+ parentThemeMap: Map?): MutableMap? {
if (parentThemeMap == null) {
return themeMap
}
@@ -53,56 +39,338 @@ internal class UIThemeBean {
}
return result
}
+
+ fun readTheme(parser: JsonParser): UIThemeBean {
+ check(parser.nextToken() == JsonToken.START_OBJECT)
+ val bean = UIThemeBean()
+ while (true) {
+ when (parser.nextToken()) {
+ JsonToken.START_OBJECT -> {
+ val fieldName = parser.currentName()
+ // ordered map is required (not clear why)
+ val map = LinkedHashMap()
+ readFlatMapFromJson(parser, map)
+ when (fieldName) {
+ "icons" -> bean.icons = map
+ "background" -> bean.background = map
+ "emptyFrameBackground" -> bean.emptyFrameBackground = map
+ "colors" -> bean.colors = map
+ "iconColorsOnSelection" -> bean.iconColorsOnSelection = map
+ "ui" -> {
+ putDefaultsIfAbsent(map)
+ bean.ui = map
+ }
+ "UIDesigner" -> {
+ parser.skipChildren()
+ }
+ else -> {
+ logger().warn("Unknown field: $fieldName")
+ }
+ }
+ }
+ JsonToken.END_OBJECT -> {
+ }
+ JsonToken.START_ARRAY -> {
+ val fieldName = parser.currentName()
+ val list = ArrayList()
+ while (parser.nextToken() != JsonToken.END_ARRAY) {
+ when (parser.currentToken()) {
+ JsonToken.VALUE_STRING -> {
+ list.add(parser.valueAsString)
+ }
+ else -> {}
+ }
+ }
+
+ when (fieldName) {
+ "additionalEditorSchemes" -> {
+ bean.additionalEditorSchemes = list
+ }
+ else -> {
+ logger().warn("Unknown field: ${parser.currentName()}")
+ }
+ }
+ }
+ JsonToken.VALUE_STRING -> {
+ when (parser.currentName()) {
+ "id" -> bean.id = parser.valueAsString
+ "name" -> bean.name = parser.valueAsString
+ "nameKey" -> bean.nameKey = parser.valueAsString
+ "parentTheme" -> bean.parentTheme = parser.valueAsString
+ "resourceBundle" -> bean.resourceBundle = parser.valueAsString
+ "author" -> bean.author = parser.valueAsString
+
+ "editorScheme" -> bean.editorScheme = parser.valueAsString
+ "editorSchemeName" -> bean.editorSchemeName = parser.valueAsString
+ }
+ }
+ JsonToken.VALUE_TRUE -> readTopLevelBoolean(parser, bean, value = true)
+ JsonToken.VALUE_FALSE -> readTopLevelBoolean(parser, bean, value = false)
+ JsonToken.FIELD_NAME -> {
+ }
+ null -> break
+ else -> {
+ logger().warn("Unknown field: ${parser.currentName()}")
+ }
+ }
+ }
+
+ putDefaultsIfAbsent(bean)
+ return bean
+ }
+
+ private fun readTopLevelBoolean(parser: JsonParser, bean: UIThemeBean, value: Boolean) {
+ when (parser.currentName()) {
+ "dark" -> bean.dark = value
+ }
+ }
}
@Transient
@JvmField
var providerClassLoader: ClassLoader? = null
- @JvmField
- var name: String? = null
- @JvmField
- var dark = false
- @JvmField
- var author: String? = null
@JvmField
var id: String? = null
+
@JvmField
- var editorScheme: String? = null
+ var name: String? = null
+
+ @JvmField
+ var nameKey: String? = null
+
@JvmField
var parentTheme: String? = null
+
@JvmField
- var additionalEditorSchemes: Array? = null
+ var resourceBundle: String? = "messages.IdeBundle"
+
+ @JvmField
+ var author: String? = null
+
+ @JvmField
+ var editorScheme: String? = null
+
+ @JvmField
+ var editorSchemeName: String? = null
+
+ @JvmField
+ var dark: Boolean = false
+
+ @JvmField
+ var additionalEditorSchemes: List? = null
+
@JvmField
var ui: MutableMap? = null
+
@JvmField
var icons: MutableMap? = null
+ @JvmField
+ var background: MutableMap? = null
+
+ @JvmField
+ var emptyFrameBackground: MutableMap? = null
+
+ @JvmField
+ var colors: MutableMap? = null
+
+ @JvmField
+ var iconColorsOnSelection: MutableMap? = null
+
@JvmField
@Transient
var patcher: IconPathPatcher? = null
- @JvmField
- var background: MutableMap? = null
- @JvmField
- var emptyFrameBackground: MutableMap? = null
- @JvmField
- var colors: MutableMap? = null
- @JvmField
- var iconColorsOnSelection: MutableMap? = null
-
- @JvmField
- var editorSchemeName: String? = null
-
@JvmField
@Transient
var colorPatcher: SvgElementColorPatcherProvider? = null
+
@JvmField
@Transient
var selectionColorPatcher: SvgElementColorPatcherProvider? = null
+}
- @JvmField
- var resourceBundle: String? = "messages.IdeBundle"
- @JvmField
- var nameKey: String? = null
-}
\ No newline at end of file
+/**
+ * Flatten example: `"Editor": { "SearchField": { "borderInsets": "7,10,7,8" } }` is flattened to
+ * `"Editor.SearchField.borderInsets": "7,10,7,8` in internal representation.
+ *
+ * Per-OS keys are also resolved as shown below:
+ * ```json
+ * "Menu.borderColor": {
+ * "os.default": "Grey12",
+ * "os.windows": "Blue12"
+ * }
+ * ```
+ *
+ * This is useful when we need to validate if a certain key was already set in [putDefaultsIfAbsent],
+ * and to uniformly override parentTheme keys regardless of used format.
+ *
+ * Note: we intentionally do not expand "*" patterns here.
+ */
+private fun readFlatMapFromJson(parser: JsonParser, result: MutableMap) {
+ check(parser.currentToken() == JsonToken.START_OBJECT)
+
+ val prefix = ArrayDeque()
+ val path = StringBuilder()
+ var currentFieldName: String? = null
+ var level = 1
+ while (true) {
+ when (parser.nextToken()) {
+ JsonToken.START_OBJECT -> {
+ level++
+ prefix.addLast(currentFieldName!!)
+ currentFieldName = null
+ }
+ JsonToken.END_OBJECT -> {
+ level--
+ prefix.pollLast()
+ currentFieldName = null
+
+ if (level == 0) {
+ assert(prefix.isEmpty())
+ break
+ }
+ }
+ JsonToken.START_ARRAY -> {
+ val fieldName = parser.currentName()
+ while (true) {
+ when (parser.nextToken()) {
+ JsonToken.END_ARRAY -> break
+ JsonToken.VALUE_STRING -> {
+ if (!prefix.isEmpty()) {
+ prefix.joinTo(buffer = path, separator = "/")
+ path.append('.')
+ }
+ path.append(fieldName)
+ result.put(path.toString(), parser.text)
+ path.setLength(0)
+ }
+ else -> {
+ logError(parser)
+ }
+ }
+ }
+ }
+ JsonToken.VALUE_STRING -> {
+ putEntry(prefix, result, parser, path) { parser.text }
+ }
+ JsonToken.VALUE_NUMBER_INT -> {
+ putEntry(prefix, result, parser, path) { parser.intValue }
+ }
+ JsonToken.VALUE_NUMBER_FLOAT -> {
+ putEntry(prefix, result, parser, path) { parser.doubleValue }
+ }
+ JsonToken.VALUE_FALSE -> {
+ putEntry(prefix, result, parser, path) { false }
+ }
+ JsonToken.VALUE_TRUE -> {
+ putEntry(prefix, result, parser, path) { true }
+ }
+ JsonToken.VALUE_NULL -> {
+ }
+ JsonToken.FIELD_NAME -> {
+ currentFieldName = parser.currentName()
+ }
+ null -> {
+ break
+ }
+ else -> {
+ logError(parser)
+ }
+ }
+ }
+
+ result.replaceAll(BiFunction { _, u -> if (u is OsDefaultValue) u.v else u })
+}
+
+private const val OS_MACOS_KEY = "os.mac"
+private const val OS_WINDOWS_KEY = "os.windows"
+private const val OS_LINUX_KEY = "os.linux"
+private const val OS_DEFAULT_KEY = "os.default"
+
+private val osKey = when {
+ SystemInfoRt.isWindows -> OS_WINDOWS_KEY
+ SystemInfoRt.isMac -> OS_MACOS_KEY
+ else -> OS_LINUX_KEY
+}
+
+private fun putEntry(prefix: Deque,
+ result: MutableMap,
+ parser: JsonParser,
+ path: StringBuilder,
+ getter: () -> Any?) {
+ if (!prefix.isEmpty()) {
+ prefix.joinTo(buffer = path, separator = ".")
+ }
+
+ val key = parser.currentName()
+ val value = getter()
+ when (key) {
+ osKey -> {
+ }
+ OS_WINDOWS_KEY, OS_MACOS_KEY, OS_LINUX_KEY -> {
+ path.setLength(0)
+ return
+ }
+ OS_DEFAULT_KEY -> {
+ val compositeKey = path.toString()
+ path.setLength(0)
+
+ val oldValue = result.putIfAbsent(compositeKey, OsDefaultValue(value))
+ if (oldValue is OsDefaultValue) {
+ logger().error("Duplicated value: (value=$value, compositeKey=$compositeKey)")
+ }
+ return
+ }
+ "UI" -> {
+ path.append(key)
+ }
+ else -> {
+ if (path.isNotEmpty()) {
+ path.append('.')
+ }
+ path.append(key)
+ }
+ }
+
+ result.put(path.toString(), value)
+ path.setLength(0)
+}
+
+private class OsDefaultValue(@JvmField val v: Any?)
+
+private fun logError(parser: JsonParser) {
+ logger().warn("JSON contains data in unsupported format (token=${parser.currentToken}): ${parser.currentValue()}")
+}
+
+/**
+ * Ensure that the old themes are not missing some vital keys.
+ *
+ * We are patching them here instead of using [com.intellij.ui.JBColor.namedColor] fallback
+ * to make sure [javax.swing.UIManager.getColor] works properly.
+ */
+private fun putDefaultsIfAbsent(theme: UIThemeBean) {
+ if (!ExperimentalUI.isNewUI()) {
+ return
+ }
+
+ var ui = theme.ui
+ if (ui == null) {
+ ui = LinkedHashMap()
+ theme.ui = ui
+ putDefaultsIfAbsent(ui)
+ }
+}
+
+private fun putDefaultsIfAbsent(ui: MutableMap) {
+ if (!ExperimentalUI.isNewUI()) {
+ return
+ }
+
+ ui.putIfAbsent("EditorTabs.underlineArc", "4")
+
+ // require theme to specify ToolWindow stripe button colors explicitly, without "*"
+ ui.putIfAbsent("ToolWindow.Button.selectedBackground", "#3573F0")
+ ui.putIfAbsent("ToolWindow.Button.selectedForeground", "#FFFFFF")
+}
diff --git a/platform/platform-impl/intellij.platform.ide.impl.iml b/platform/platform-impl/intellij.platform.ide.impl.iml
index eea239789ecb..fc8806c84cb7 100644
--- a/platform/platform-impl/intellij.platform.ide.impl.iml
+++ b/platform/platform-impl/intellij.platform.ide.impl.iml
@@ -119,7 +119,6 @@
-
diff --git a/platform/platform-impl/src/com/intellij/ide/bootstrap/ApplicationLoader.kt b/platform/platform-impl/src/com/intellij/ide/bootstrap/ApplicationLoader.kt
index ea2922e96509..68195018ad33 100644
--- a/platform/platform-impl/src/com/intellij/ide/bootstrap/ApplicationLoader.kt
+++ b/platform/platform-impl/src/com/intellij/ide/bootstrap/ApplicationLoader.kt
@@ -233,9 +233,11 @@ private suspend fun preInitApp(app: ApplicationImpl,
euaTaskDeferred?.await()?.invoke()
- val installIconPatcherJob = if (loadIconMapping == null) null else launch {
- loadIconMapping.join()
- ExperimentalUI.getInstance().installIconPatcher()
+ if (loadIconMapping != null) {
+ launch {
+ loadIconMapping.join()
+ ExperimentalUI.getInstance().installIconPatcher()
+ }
}
coroutineScope {
diff --git a/platform/platform-impl/src/com/intellij/ide/gdpr/ConsentAttributes.kt b/platform/platform-impl/src/com/intellij/ide/gdpr/ConsentAttributes.kt
index de9300276b0a..890fb6d6a5ee 100644
--- a/platform/platform-impl/src/com/intellij/ide/gdpr/ConsentAttributes.kt
+++ b/platform/platform-impl/src/com/intellij/ide/gdpr/ConsentAttributes.kt
@@ -1,15 +1,55 @@
// 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.
-package com.intellij.ide.gdpr;
+package com.intellij.ide.gdpr
+
+import kotlinx.serialization.ExperimentalSerializationApi
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.encodeToString
+import kotlinx.serialization.json.Json
/**
* Data structure describing all possible Consent JSON attributes
*/
-final class ConsentAttributes {
- public String consentId;
- public String version;
- public String text;
- public String printableName;
- public boolean accepted;
- public boolean deleted;
- public long acceptanceTime;
+@Serializable
+internal class ConsentAttributes {
+ companion object {
+ @OptIn(ExperimentalSerializationApi::class)
+ private val jsonConfig by lazy {
+ Json {
+ ignoreUnknownKeys = true
+ isLenient = true
+ encodeDefaults = false
+ prettyPrint = true
+ prettyPrintIndent = " "
+ }
+ }
+
+ fun readListFromJson(json: String): List {
+ return jsonConfig.decodeFromString>(json)
+ }
+
+ fun writeListToJson(list: List): String {
+ return jsonConfig.encodeToString>(list)
+ }
+ }
+
+ @JvmField
+ var consentId: String? = null
+
+ @JvmField
+ var version: String? = null
+
+ @JvmField
+ var text: String? = null
+
+ @JvmField
+ var printableName: String? = null
+
+ @JvmField
+ var accepted: Boolean = false
+
+ @JvmField
+ var deleted: Boolean = false
+
+ @JvmField
+ var acceptanceTime: Long = 0
}
diff --git a/platform/platform-impl/src/com/intellij/ide/gdpr/ConsentOptions.java b/platform/platform-impl/src/com/intellij/ide/gdpr/ConsentOptions.java
index 6b8c0d744944..6963386aacec 100644
--- a/platform/platform-impl/src/com/intellij/ide/gdpr/ConsentOptions.java
+++ b/platform/platform-impl/src/com/intellij/ide/gdpr/ConsentOptions.java
@@ -1,9 +1,6 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.ide.gdpr;
-import com.fasterxml.jackson.jr.ob.JSON;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
import com.intellij.diagnostic.LoadingState;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ApplicationNamesInfo;
@@ -424,14 +421,16 @@ public final class ConsentOptions {
}
private @NotNull Collection fromJson(@Nullable String json) {
+ if (json == null || json.isEmpty()) {
+ return Collections.emptyList();
+ }
+
try {
- List data = json == null || json.isEmpty() ? null : JSON.std.listOfFrom(ConsentAttributes.class, json);
- if (data != null) {
- for (ConsentAttributes attributes : data) {
- attributes.consentId = lookupConsentID(attributes.consentId);
- }
- return data;
+ List data = ConsentAttributes.Companion.readListFromJson(json);
+ for (ConsentAttributes attributes : data) {
+ attributes.consentId = lookupConsentID(attributes.consentId);
}
+ return data;
}
catch (Throwable e) {
LOG.info(e);
@@ -440,15 +439,14 @@ public final class ConsentOptions {
}
private @NotNull String consentsToJson(@NotNull Stream consents) {
- Gson gson = new GsonBuilder().disableHtmlEscaping().create();
- return gson.toJson(consents.map(consent -> {
+ return ConsentAttributes.Companion.writeListToJson(consents.map(consent -> {
final ConsentAttributes attribs = consent.toConsentAttributes();
final String prefix = getProductConsentKind(myProductCode, attribs.consentId);
if (prefix != null) {
attribs.consentId = prefix;
}
return attribs;
- }).toArray());
+ }).toList());
}
private static @NotNull String confirmedConsentToExternalString(@NotNull Stream consents) {
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/IconMapLoader.kt b/platform/platform-impl/src/com/intellij/ide/ui/IconMapLoader.kt
index 8a6cc958841d..0294854c3df0 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/IconMapLoader.kt
+++ b/platform/platform-impl/src/com/intellij/ide/ui/IconMapLoader.kt
@@ -138,11 +138,12 @@ private fun readDataFromJson(parser: JsonParser, result: MutableMap, parser: JsonParser, path: StringBuilder) {
- val oldValue = result.get(parser.text)
- if (oldValue != null && oldValue != path.toString()) {
- logger().error("Double icon mapping: ${parser.text} -> $oldValue or $path")
+ val key = parser.text
+ val p = path.toString()
+ val oldValue = result.put(key, p)
+ if (oldValue != null && oldValue != p) {
+ logger().error("Double icon mapping: $key -> $oldValue or $path")
}
- result.put(parser.text, path.toString())
}
private fun logError(parser: JsonParser) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java
index 275607945a50..e1126459b568 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java
@@ -319,7 +319,7 @@ public final class EditorColorsManagerImpl extends EditorColorsManager implement
for (UIThemeLookAndFeelInfo laf : UiThemeProviderListManager.Companion.getInstance().getLaFs()) {
UITheme theme = laf.getTheme();
- String[] schemes = theme.getAdditionalEditorSchemes();
+ List schemes = theme.getAdditionalEditorSchemes();
PluginDescriptor pluginDescriptor = getPluginDescriptor(theme);
if (schemes != null) {
for (String scheme : schemes) {