CPP-778 Support for semantic per-variable highlighting (HighlightVisitor approach was applied)

This commit is contained in:
Alexey Utkin
2016-07-01 17:28:30 +03:00
parent ebc92ac640
commit 4a3796574d
8 changed files with 86 additions and 188 deletions
@@ -19,10 +19,9 @@ import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
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.colors.TextAttributesScheme;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringHash;
@@ -35,12 +34,10 @@ import java.awt.*;
public class RainbowHighlighter {
private final float[] myFloats;
@NotNull private final EditorColorsScheme myColorsScheme;
@NotNull private final Color myDefaultBackground;
@NotNull private final TextAttributesScheme myColorsScheme;
public RainbowHighlighter(@Nullable EditorColorsScheme colorsScheme, @Nullable Color background) {
public RainbowHighlighter(@Nullable TextAttributesScheme colorsScheme) {
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);
}
@@ -58,21 +55,8 @@ public class RainbowHighlighter {
final float colors = 36.0f;
final float v = Math.round(Math.abs(colors * hash) / Integer.MAX_VALUE) / colors;
//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(bkColor)
);
return TextAttributes.fromFlyweight(origin.getFlyweight().withForeground(Color.getHSBColor(v, 0.7f, myFloats[2] + .3f)));
}
public HighlightInfo getInfo(
@@ -1,41 +0,0 @@
/*
* 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 interface RainbowProvider {
ExtensionPointName<RainbowProvider> EP_NAME = ExtensionPointName.create("com.intellij.rainbowProvider");
@NotNull
static RainbowProvider[] getRainbowFileProcessors() {
return Extensions.getExtensions(EP_NAME);
}
boolean isValidContext(@NotNull final PsiFile file);
List<HighlightInfo> getHighlights(@NotNull PsiFile file,
@NotNull RainbowHighlighter highlighter,
@NotNull ProgressIndicator progress);
}
@@ -0,0 +1,78 @@
/*
* 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.codeInsight.daemon.impl.HighlightVisitor;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightInfoHolder;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiRecursiveElementWalkingVisitor;
import org.jetbrains.annotations.NotNull;
public abstract class RainbowVisitor implements HighlightVisitor {
private HighlightInfoHolder myHolder;
@NotNull
protected abstract PsiRecursiveElementWalkingVisitor getVisitor(@NotNull final RainbowHighlighter highlighter);
@NotNull
@Override
public abstract HighlightVisitor clone();
@Override
public void visit(@NotNull PsiElement element) {
RainbowHighlighter highlighter = new RainbowHighlighter(myHolder.getColorsScheme());
element.accept(getVisitor(highlighter));
}
@Override
public boolean analyze(@NotNull PsiFile file,
boolean updateWholeFile,
@NotNull HighlightInfoHolder holder,
@NotNull Runnable action) {
if (RainbowHighlighter.isRainbowEnabled()) {
myHolder = holder;
try {
action.run();
}
finally {
myHolder = null;
}
}
return true;
}
@Override
public int order() {
return 1;
}
protected void addInfo(HighlightInfo highlightInfo) {
myHolder.add(highlightInfo);
}
public static boolean existsPassSuitableForFile(@NotNull PsiFile file) {
for (HighlightVisitor visitor : Extensions.getExtensions(HighlightVisitor.EP_HIGHLIGHT_VISITOR, file.getProject())) {
if (visitor instanceof RainbowVisitor && visitor.suitableForFile(file)) {
return true;
}
}
return false;
}
}
@@ -19,7 +19,7 @@ package com.intellij.codeInsight.daemon.impl;
import com.intellij.codeHighlighting.RainbowHighlighter;
import com.intellij.codeInsight.daemon.GutterMark;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInsight.daemon.RainbowProvider;
import com.intellij.codeInsight.daemon.RainbowVisitor;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.IntentionManager;
import com.intellij.codeInspection.*;
@@ -187,19 +187,15 @@ public class HighlightInfo implements Segment {
isLikeVariable(type.getAttributesKey())) {
String text = element.getContainingFile().getText();
String name = text.substring(startOffset, endOffset);
attributes = new RainbowHighlighter(colorsScheme, null).getAttributes(name, attributes);
attributes = new RainbowHighlighter(colorsScheme).getAttributes(name, attributes);
}
return attributes;
}
@Contract("null -> false")
public static boolean isByPass(@Nullable PsiElement element) {
if (element == null) return false;
PsiFile containingFile = element.getContainingFile();
for (RainbowProvider processor : RainbowProvider.getRainbowFileProcessors()) {
if (processor.isValidContext(containingFile)) return true;
}
return false;
return element != null
&& RainbowVisitor.existsPassSuitableForFile(element.getContainingFile());
}
@Contract("null -> false")
@@ -1,63 +0,0 @@
/*
* 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.impl;
import com.intellij.codeHighlighting.RainbowHighlighter;
import com.intellij.codeHighlighting.TextEditorHighlightingPass;
import com.intellij.codeInsight.daemon.RainbowProvider;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.impl.EditorImpl;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
public class RainbowIdentifierHighlighterPass extends TextEditorHighlightingPass {
protected final PsiFile myFile;
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;
}
@Override
public void doCollectInformation(@NotNull final ProgressIndicator progress) {
final List<HighlightInfo> infos = new ArrayList<>();
// 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));
}
}
myHighlight = infos;
}
@Override
public void doApplyInformationToEditor() {
if (myHighlight == null || myDocument == null) return;
UpdateHighlightersUtil
.setHighlightersToEditor(myProject, myDocument, 0, myFile.getTextLength(), myHighlight, getColorsScheme(), getId());
}
}
@@ -1,49 +0,0 @@
/*
* 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.impl;
import com.intellij.codeHighlighting.*;
import com.intellij.openapi.components.AbstractProjectComponent;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
public class RainbowIdentifierHighlighterPassFactory extends AbstractProjectComponent implements TextEditorHighlightingPassFactory {
public RainbowIdentifierHighlighterPassFactory(Project project, TextEditorHighlightingPassRegistrar highlightingPassRegistrar) {
super(project);
highlightingPassRegistrar.registerTextEditorHighlightingPass(this,
TextEditorHighlightingPassRegistrar.Anchor.BEFORE,
Pass.UPDATE_FOLDING,
false, false);
}
@Override
@NonNls
@NotNull
public String getComponentName() {
return "RainbowIdentifierPassFactory";
}
@Override
public TextEditorHighlightingPass createHighlightingPass(@NotNull final PsiFile file, @NotNull final Editor editor) {
if (RainbowHighlighter.isRainbowEnabled()) {
return new RainbowIdentifierHighlighterPass(file, editor);
}
return null;
}
}
@@ -95,9 +95,6 @@
<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,10 +154,6 @@
<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/>