forgot to check length()
[idea/community.git] / platform / analysis-impl / src / com / intellij / codeHighlighting / RainbowHighlighter.java
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.codeHighlighting;
17
18 import com.intellij.codeInsight.daemon.impl.HighlightInfo;
19 import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
20 import com.intellij.lang.annotation.HighlightSeverity;
21 import com.intellij.openapi.application.ApplicationManager;
22 import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
23 import com.intellij.openapi.editor.colors.EditorColorsManager;
24 import com.intellij.openapi.editor.colors.TextAttributesKey;
25 import com.intellij.openapi.editor.colors.TextAttributesScheme;
26 import com.intellij.openapi.editor.markup.TextAttributes;
27 import com.intellij.openapi.util.registry.Registry;
28 import com.intellij.openapi.util.text.StringUtil;
29 import com.intellij.psi.PsiElement;
30 import com.intellij.ui.ColorUtil;
31 import com.intellij.ui.JBColor;
32 import com.intellij.util.containers.ContainerUtil;
33 import org.jetbrains.annotations.NotNull;
34 import org.jetbrains.annotations.Nullable;
35
36 import java.awt.*;
37 import java.util.List;
38
39 public class RainbowHighlighter {
40   private static final JBColor[] RAINBOW_JB_COLORS_DEFAULT = {
41     new JBColor(0x9b3b6a, 0x529d52),
42     new JBColor(0x114d77, 0xbe7070),
43     new JBColor(0xbc8650, 0x3d7676),
44     new JBColor(0x005910, 0xbe9970),
45     new JBColor(0xbc5150, 0x9d527c),
46   };
47   private static final TextAttributesKey[] RAINBOW_COLOR_KEYS = new TextAttributesKey[RAINBOW_JB_COLORS_DEFAULT.length];
48   private static final int RAINBOW_COLORS_BETWEEN = 4;
49   private static final String UNIT_TEST_COLORS = "#000001,#000002,#000003,#000004"; // Do not modify!
50   static {
51     for (int i = 0; i < RAINBOW_JB_COLORS_DEFAULT.length; ++i) {
52       JBColor jbColor = RAINBOW_JB_COLORS_DEFAULT[i];
53       TextAttributes textAttributes = new TextAttributes(jbColor, null, null, null, Font.PLAIN);
54       RAINBOW_COLOR_KEYS[i] = TextAttributesKey.createTextAttributesKey("RAINBOW_COLOR" + i, textAttributes);
55     }
56   }
57
58   @NotNull private final TextAttributesScheme myColorsScheme;
59   @NotNull private final Color[] myRainbowColors;
60
61   public RainbowHighlighter(@Nullable TextAttributesScheme colorsScheme) {
62     myColorsScheme = colorsScheme != null ? colorsScheme : EditorColorsManager.getInstance().getGlobalScheme();
63     myRainbowColors = generateColorSequence(myColorsScheme);
64   }
65
66   public static final HighlightInfoType RAINBOW_ELEMENT = new HighlightInfoType.HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, DefaultLanguageHighlighterColors.CONSTANT);
67
68   public static boolean isRainbowEnabled() {
69     return Registry.is("editor.rainbow.identifiers", false);
70   }
71
72   @NotNull
73   private Color calculateForeground(int colorIndex) {
74     return myRainbowColors[colorIndex];
75   }
76
77   public int getColorsCount() {
78     return myRainbowColors.length;
79   }
80
81   @NotNull
82   private static Color[] generateColorSequence(@NotNull TextAttributesScheme colorsScheme) {
83     String colorDump = ApplicationManager.getApplication().isUnitTestMode()
84                        ? UNIT_TEST_COLORS
85                        : Registry.get("rainbow.highlighter.colors").asString();
86
87     final List<String> registryColors = StringUtil.split(colorDump, ",");
88     if (!registryColors.isEmpty()) {
89       return registryColors.stream().map(s -> ColorUtil.fromHex(s.trim())).toArray(Color[]::new);
90     }
91
92     List<Color> foregroundColors = ContainerUtil.map(RAINBOW_COLOR_KEYS, key -> colorsScheme.getAttributes(key).getForegroundColor());
93     List<Color> colors = ColorGenerator.generateLinearColorSequence(foregroundColors, RAINBOW_COLORS_BETWEEN);
94     return colors.toArray(new Color[colors.size()]);
95   }
96
97   public HighlightInfo getInfo(int colorIndex, @Nullable PsiElement id, @Nullable TextAttributesKey colorKey) {
98     if (id == null) {
99       return null;
100     }
101     if (colorKey == null) {
102       colorKey = DefaultLanguageHighlighterColors.LOCAL_VARIABLE;
103     }
104     return HighlightInfo
105       .newHighlightInfo(RAINBOW_ELEMENT)
106       .textAttributes(TextAttributes
107                         .fromFlyweight(myColorsScheme
108                                          .getAttributes(colorKey)
109                                          .getFlyweight()
110                                          .withForeground(calculateForeground(colorIndex))))
111       .range(id)
112       .create();
113   }
114 }