[ui] IJPL-226841 Fix show preview for color keys when key name includes - (dash)

GitOrigin-RevId: 326b2f68d21162b0a97bccde2d1eef7ca6040941
This commit is contained in:
Yuriy Artamonov
2026-02-09 13:47:57 +01:00
committed by intellij-monorepo-bot
parent 80df51b34f
commit 0150e732a6
2 changed files with 49 additions and 29 deletions

View File

@@ -23,11 +23,13 @@ import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.CachedValueProvider.Result;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.ui.ColorChooserService;
import com.intellij.ui.ColorLineMarkerProvider;
import com.intellij.ui.ColorUtil;
import com.intellij.ui.scale.JBUIScale;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.ColorIcon;
import com.intellij.util.ui.EmptyIcon;
import org.jetbrains.annotations.NotNull;
@@ -35,8 +37,12 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.Icon;
import java.awt.Color;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.regex.Pattern;
final class ThemeColorAnnotator implements Annotator, DumbAware {
@@ -46,6 +52,8 @@ final class ThemeColorAnnotator implements Annotator, DumbAware {
private static final int HEX_COLOR_LENGTH_RGB = 7;
private static final int HEX_COLOR_LENGTH_RGBA = 9;
private static final Pattern NAMED_COLOR_MASK = Pattern.compile("[\\w-]+");
@Override
public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
if (!isColorLineMarkerProviderEnabled() || !isTargetElement(element, holder.getCurrentAnnotationSession().getFile())) return;
@@ -73,7 +81,7 @@ final class ThemeColorAnnotator implements Annotator, DumbAware {
}
static boolean isNamedColor(String text) {
return StringUtil.isLatinAlphanumeric(text);
return NAMED_COLOR_MASK.matcher(text).matches();
}
static boolean isColorCode(@Nullable String text) {
@@ -191,35 +199,46 @@ final class ThemeColorAnnotator implements Annotator, DumbAware {
}
}
private static Map<String, String> getNamedColorsMap(@NotNull JsonFile file) {
return CachedValuesManager.getCachedValue(file, () -> {
Map<String, String> namedColorsMap = new HashMap<>();
List<JsonProperty> colors = ThemeJsonUtil.getNamedColors(file);
for (JsonProperty property : colors) {
JsonValue value = property.getValue();
if (value instanceof JsonStringLiteral) {
namedColorsMap.put(property.getName(), ((JsonStringLiteral)value).getValue());
}
}
return Result.create(Map.copyOf(namedColorsMap), PsiModificationTracker.MODIFICATION_COUNT);
});
}
private @Nullable Color findNamedColor(@NotNull String colorText) {
final PsiFile file = myLiteral.getContainingFile();
PsiFile file = myLiteral.getContainingFile();
if (!(file instanceof JsonFile)) return null;
final List<JsonProperty> colors = ThemeJsonUtil.getNamedColors((JsonFile)file);
String colorValue = findNamedColorValue(colors, colorText);
if (colorValue == null) {
Map<String, String> namedColorsMap = getNamedColorsMap((JsonFile)file);
String colorValue = findNamedColorValue(colorText, namedColorsMap, new HashSet<>());
if (colorValue == null || !colorValue.startsWith("#")) {
return null;
}
if (!colorValue.startsWith("#")) {
String nextColorValue = findNamedColorValue(colors, colorValue);
if (nextColorValue != null) {
colorValue = nextColorValue;
}
}
return parseColor(colorValue);
}
private static @Nullable String findNamedColorValue(List<JsonProperty> colors, @NotNull String colorText) {
final JsonProperty namedColor = ContainerUtil.find(colors, property -> property.getName().equals(colorText));
if (namedColor == null) return null;
private static @Nullable String findNamedColorValue(@NotNull String colorName,
@NotNull Map<String, String> namedColorsMap,
@NotNull Set<String> visited) {
if (!visited.add(colorName)) return null; // cycle detected in resolve!
final JsonValue value = namedColor.getValue();
if ((value instanceof JsonStringLiteral literal)) {
return literal.getValue();
String colorValue = namedColorsMap.get(colorName);
if (colorValue == null) return null;
if (colorValue.startsWith("#")) {
return colorValue;
}
return null;
return findNamedColorValue(colorValue, namedColorsMap, visited);
}
private static boolean isRgbaColorHex(@NotNull String colorHex) {

View File

@@ -1,7 +1,6 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.idea.devkit.themes;
import com.intellij.json.psi.JsonLiteral;
import com.intellij.json.psi.JsonProperty;
import com.intellij.json.psi.JsonStringLiteral;
import com.intellij.psi.PsiElement;
@@ -14,20 +13,20 @@ import java.util.regex.Pattern;
final class ThemeJsonNamedColorPsiReferenceProvider extends PsiReferenceProvider {
private static final Pattern COLOR_N_PATTERN = Pattern.compile("Color\\d+");
private static final String COLORS_BLOCK_KEY = "colors";
@Override
public PsiReference @NotNull [] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
if (!(element instanceof JsonLiteral literal)) return PsiReference.EMPTY_ARRAY;
if (element instanceof JsonStringLiteral
&& ThemeColorAnnotator.isColorCode(((JsonStringLiteral)element).getValue())) {
return PsiReference.EMPTY_ARRAY;
}
if (!(element instanceof JsonStringLiteral literal)) return PsiReference.EMPTY_ARRAY;
PsiElement parent = literal.getParent();
if (parent instanceof JsonProperty property) {
String name = property.getName();
if (property.getValue() == literal) { // inside value of property
if (ThemeColorAnnotator.isColorCode(literal.getValue())) {
return PsiReference.EMPTY_ARRAY;
}
if (isKeyInteresting(name)) {
return new PsiReference[]{new ThemeJsonNamedColorPsiReference(literal)};
}
@@ -37,7 +36,9 @@ final class ThemeJsonNamedColorPsiReferenceProvider extends PsiReferenceProvider
PsiElement greatGrandParent = grandParent.getParent();
if (greatGrandParent instanceof JsonProperty parentProperty) {
String parentName = parentProperty.getName();
if (COLOR_N_PATTERN.matcher(parentName).matches() || isKeyInteresting(parentName)) {
if (COLOR_N_PATTERN.matcher(parentName).matches()
|| isKeyInteresting(parentName)
|| COLORS_BLOCK_KEY.equals(parentName)) {
return new PsiReference[]{new ThemeJsonNamedColorPsiReference(literal)};
}
}