mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
CPP-778 Support for semantic per-variable highlighting (fix Darcula background, before code inspection pass, EP approach)
This commit is contained in:
@@ -15,27 +15,41 @@
|
||||
*/
|
||||
package com.intellij.codeHighlighting;
|
||||
|
||||
import com.intellij.codeInsight.daemon.RainbowProvider;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
|
||||
import com.intellij.openapi.editor.colors.TextAttributesScheme;
|
||||
import com.intellij.openapi.editor.HighlighterColors;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringHash;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.containers.hash.HashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class RainbowHighlighter {
|
||||
private final float[] myFloats;
|
||||
private static final HashSet<Language> BY_PASS_LANGUAGES = new HashSet<Language>();
|
||||
@NotNull private final EditorColorsScheme myColorsScheme;
|
||||
@NotNull private final Color myDefaultBackground;
|
||||
|
||||
public RainbowHighlighter(@NotNull TextAttributesScheme colorsScheme) {
|
||||
float[] components = colorsScheme.getAttributes(DefaultLanguageHighlighterColors.CONSTANT).getForegroundColor().getRGBColorComponents(null);
|
||||
private static final HashSet<Language> BY_PASS_LANGUAGES = new HashSet<Language>();
|
||||
static {
|
||||
RainbowProvider.initRainbow();
|
||||
}
|
||||
|
||||
public RainbowHighlighter(@Nullable EditorColorsScheme colorsScheme, @Nullable Color background) {
|
||||
myColorsScheme = colorsScheme != null ? colorsScheme : EditorColorsManager.getInstance().getGlobalScheme();
|
||||
myDefaultBackground = background != null ? background : myColorsScheme.getDefaultBackground();
|
||||
float[] components = myColorsScheme.getAttributes(DefaultLanguageHighlighterColors.CONSTANT).getForegroundColor().getRGBColorComponents(null);
|
||||
myFloats = Color.RGBtoHSB((int)(255 * components[0]), (int)(255 * components[0]), (int)(255 * components[0]), null);
|
||||
}
|
||||
|
||||
@@ -62,11 +76,34 @@ public class RainbowHighlighter {
|
||||
//System.out.println("name = " + name + " \tv=" + v);
|
||||
final Color color = Color.getHSBColor(v, 0.7f, myFloats[2] + .3f);
|
||||
|
||||
Color bkColor = origin.getBackgroundColor();
|
||||
if (bkColor == null) {
|
||||
bkColor = myColorsScheme.getAttributes(HighlighterColors.TEXT).getBackgroundColor();
|
||||
}
|
||||
if (bkColor == null) {
|
||||
bkColor = myDefaultBackground;
|
||||
}
|
||||
return TextAttributes.fromFlyweight(origin
|
||||
.getFlyweight()
|
||||
.withForeground(color)
|
||||
//fixme: uta: foreground color is not activated for local variables without background color reset
|
||||
.withBackground(UIManager.getColor("EditorPane.background"))
|
||||
.withBackground(bkColor)
|
||||
);
|
||||
}
|
||||
|
||||
public HighlightInfo getInfo(
|
||||
@Nullable String nameKey,
|
||||
@Nullable PsiElement id,
|
||||
@Nullable TextAttributesKey colorKey) {
|
||||
|
||||
if (id == null || nameKey == null || StringUtil.isEmpty(nameKey)) return null;
|
||||
if (colorKey == null) colorKey = DefaultLanguageHighlighterColors.LOCAL_VARIABLE;
|
||||
final TextAttributes attributes = getAttributes(nameKey, myColorsScheme.getAttributes(colorKey));
|
||||
return HighlightInfo
|
||||
.newHighlightInfo(RAINBOW_ELEMENT)
|
||||
.textAttributes(attributes)
|
||||
.range(id)
|
||||
.create();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.codeInsight.daemon;
|
||||
|
||||
import com.intellij.codeHighlighting.RainbowHighlighter;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class RainbowProvider {
|
||||
static ExtensionPointName<RainbowProvider> EP_NAME = ExtensionPointName.create("com.intellij.rainbowProvider");
|
||||
|
||||
@NotNull
|
||||
public static RainbowProvider[] getRainbowFileProcessors() {
|
||||
return Extensions.getExtensions(EP_NAME);
|
||||
}
|
||||
|
||||
public static void initRainbow() {
|
||||
for (RainbowProvider processor : getRainbowFileProcessors()) {
|
||||
processor.init();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void init();
|
||||
|
||||
public abstract boolean isValidContext(@NotNull final PsiFile file);
|
||||
|
||||
public abstract List<HighlightInfo> getHighlights(@NotNull PsiFile file,
|
||||
@NotNull RainbowHighlighter highlighter,
|
||||
@NotNull ProgressIndicator progress);
|
||||
}
|
||||
@@ -185,7 +185,7 @@ public class HighlightInfo implements Segment {
|
||||
isLikeVariable(type.getAttributesKey())) {
|
||||
String text = element.getContainingFile().getText();
|
||||
String name = text.substring(startOffset, endOffset);
|
||||
attributes = new RainbowHighlighter(colorsScheme).getAttributes(name, attributes);
|
||||
attributes = new RainbowHighlighter(colorsScheme, null).getAttributes(name, attributes);
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
||||
+17
-46
@@ -18,75 +18,46 @@ package com.intellij.codeInsight.daemon.impl;
|
||||
|
||||
import com.intellij.codeHighlighting.RainbowHighlighter;
|
||||
import com.intellij.codeHighlighting.TextEditorHighlightingPass;
|
||||
import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
|
||||
import com.intellij.codeInsight.daemon.RainbowProvider;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.editor.impl.EditorImpl;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class RainbowIdentifierHighlighterPass extends TextEditorHighlightingPass {
|
||||
protected final PsiFile myFile;
|
||||
protected final RainbowHighlighter myRainbowHighlighter;
|
||||
protected List<HighlightInfo> toHighlight;
|
||||
protected final EditorColorsScheme myEditorColorsScheme;
|
||||
protected List<HighlightInfo> myHighlight;
|
||||
protected final Color myBackgroundColor;
|
||||
|
||||
protected RainbowIdentifierHighlighterPass(@NotNull PsiFile file, @NotNull Editor editor) {
|
||||
super(file.getProject(), editor.getDocument(), false);
|
||||
myBackgroundColor = (editor instanceof EditorImpl) ? ((EditorImpl)editor).getBackgroundColor() : null;
|
||||
myFile = file;
|
||||
myEditorColorsScheme = editor.getColorsScheme();
|
||||
myRainbowHighlighter = new RainbowHighlighter(myEditorColorsScheme);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doCollectInformation(@NotNull final ProgressIndicator progress) {
|
||||
// reference implementation!
|
||||
final List<HighlightInfo> infos = new ArrayList<>();
|
||||
myFile.accept(new PsiRecursiveElementWalkingVisitor() {
|
||||
@Override
|
||||
public void visitElement(PsiElement e) {
|
||||
final HighlightInfo attrs;
|
||||
if (e instanceof PsiReference) {
|
||||
attrs = getInfo(e.getText(), e, null);
|
||||
}
|
||||
else if (e instanceof PsiNameIdentifierOwner) {
|
||||
PsiNameIdentifierOwner identifierOwner = (PsiNameIdentifierOwner)e;
|
||||
attrs = getInfo(identifierOwner.getName(), identifierOwner.getNameIdentifier(), null);
|
||||
}
|
||||
else {
|
||||
attrs = null;
|
||||
}
|
||||
if (attrs != null) {
|
||||
infos.add(attrs);
|
||||
}
|
||||
super.visitElement(e);
|
||||
|
||||
// myBackgroundColor takes into account "read only" editors
|
||||
final RainbowHighlighter rainbowHighlighter = new RainbowHighlighter(getColorsScheme(), myBackgroundColor);
|
||||
for (RainbowProvider processor : RainbowProvider.getRainbowFileProcessors()) {
|
||||
if (processor.isValidContext(myFile)) {
|
||||
infos.addAll(processor.getHighlights(myFile, rainbowHighlighter, progress));
|
||||
}
|
||||
});
|
||||
toHighlight = infos;
|
||||
}
|
||||
myHighlight = infos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doApplyInformationToEditor() {
|
||||
if (toHighlight == null || myDocument == null) return;
|
||||
UpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, 0, myFile.getTextLength(), toHighlight, getColorsScheme(), getId());
|
||||
}
|
||||
|
||||
protected HighlightInfo getInfo(@Nullable String nameKey, @Nullable PsiElement id, @Nullable TextAttributesKey colorKey) {
|
||||
if (id == null || nameKey == null || StringUtil.isEmpty(nameKey)) return null;
|
||||
if (colorKey == null) colorKey = DefaultLanguageHighlighterColors.LOCAL_VARIABLE;
|
||||
final TextAttributes attributes = myRainbowHighlighter.getAttributes(nameKey,
|
||||
myEditorColorsScheme.getAttributes(colorKey));
|
||||
return HighlightInfo
|
||||
.newHighlightInfo(RainbowHighlighter.RAINBOW_ELEMENT)
|
||||
.textAttributes(attributes)
|
||||
.range(id)
|
||||
.create();
|
||||
if (myHighlight == null || myDocument == null) return;
|
||||
UpdateHighlightersUtil
|
||||
.setHighlightersToEditor(myProject, myDocument, 0, myFile.getTextLength(), myHighlight, getColorsScheme(), getId());
|
||||
}
|
||||
}
|
||||
|
||||
+6
-26
@@ -23,13 +23,13 @@ import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Language-dependent implementation need to be inherited from this class and
|
||||
*/
|
||||
public class RainbowIdentifierHighlighterPassFactory extends AbstractProjectComponent implements TextEditorHighlightingPassFactory {
|
||||
public RainbowIdentifierHighlighterPassFactory(Project project, TextEditorHighlightingPassRegistrar highlightingPassRegistrar) {
|
||||
super(project);
|
||||
highlightingPassRegistrar.registerTextEditorHighlightingPass(this, new int[]{Pass.UPDATE_ALL}, null, false, -1);
|
||||
highlightingPassRegistrar.registerTextEditorHighlightingPass(this,
|
||||
TextEditorHighlightingPassRegistrar.Anchor.BEFORE,
|
||||
Pass.UPDATE_FOLDING,
|
||||
false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -41,29 +41,9 @@ public class RainbowIdentifierHighlighterPassFactory extends AbstractProjectComp
|
||||
|
||||
@Override
|
||||
public TextEditorHighlightingPass createHighlightingPass(@NotNull final PsiFile file, @NotNull final Editor editor) {
|
||||
if (RainbowHighlighter.isRainbowEnabled() && isValidContext(file, editor)) {
|
||||
return getRainbowPass(file, editor);
|
||||
if (RainbowHighlighter.isRainbowEnabled()) {
|
||||
return new RainbowIdentifierHighlighterPass(file, editor);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Need to be rewritten in language-dependent implementation.
|
||||
* Default implementation colors all identifiers in [PsiReference] and [PsiNameIdentifierOwner] elements.
|
||||
*/
|
||||
@NotNull
|
||||
protected RainbowIdentifierHighlighterPass getRainbowPass(@NotNull PsiFile file, @NotNull Editor editor) {
|
||||
return new RainbowIdentifierHighlighterPass(file, editor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Need to be rewritten in language-dependent implementation.
|
||||
* For example:
|
||||
* return file instanceof JavaFile;
|
||||
* Default implementation works for any language.
|
||||
*/
|
||||
protected boolean isValidContext(@NotNull final PsiFile file, @NotNull Editor editor) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +95,9 @@
|
||||
<extensionPoint name="severitiesProvider"
|
||||
interface="com.intellij.codeInsight.daemon.impl.SeveritiesProvider"/>
|
||||
|
||||
<extensionPoint name="rainbowProvider"
|
||||
interface="com.intellij.codeInsight.daemon.RainbowProvider"/>
|
||||
|
||||
<extensionPoint name="implicitUsageProvider"
|
||||
interface="com.intellij.codeInsight.daemon.ImplicitUsageProvider"/>
|
||||
|
||||
|
||||
@@ -154,6 +154,10 @@
|
||||
<implementation-class>com.intellij.codeInsight.daemon.impl.CodeFoldingPassFactory</implementation-class>
|
||||
<skipForDefaultProject/>
|
||||
</component>
|
||||
<component>
|
||||
<implementation-class>com.intellij.codeInsight.daemon.impl.RainbowIdentifierHighlighterPassFactory</implementation-class>
|
||||
<skipForDefaultProject/>
|
||||
</component>
|
||||
<component>
|
||||
<implementation-class>com.intellij.codeInsight.daemon.impl.IndentsPassFactory</implementation-class>
|
||||
<skipForDefaultProject/>
|
||||
|
||||
Reference in New Issue
Block a user