Added highlighting for properties depending on their container and presence of backing field.

This commit is contained in:
Evgeny Gerashchenko
2012-03-30 19:00:01 +04:00
parent 696e6828ea
commit 06cae390e7
6 changed files with 127 additions and 72 deletions
@@ -1,68 +0,0 @@
/*
* Copyright 2010-2012 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 org.jetbrains.jet.plugin.highlighter;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
class BackingFieldHighlightingVisitor extends AfterAnalysisHighlightingVisitor {
BackingFieldHighlightingVisitor(AnnotationHolder holder, BindingContext bindingContext) {
super(holder, bindingContext);
}
@Override
public void visitProperty(@NotNull JetProperty property) {
VariableDescriptor propertyDescriptor = bindingContext.get(BindingContext.VARIABLE, property);
if (propertyDescriptor instanceof PropertyDescriptor) {
Boolean backingFieldRequired = bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor)propertyDescriptor);
if (Boolean.TRUE.equals(backingFieldRequired)) {
putBackingFieldAnnotation(holder, property);
}
}
}
@Override
public void visitParameter(@NotNull JetParameter parameter) {
PropertyDescriptor propertyDescriptor = bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter);
if (propertyDescriptor != null) {
Boolean backingFieldRequired = bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor);
if (Boolean.TRUE.equals(backingFieldRequired)) {
putBackingFieldAnnotation(holder, parameter);
}
}
}
@Override
public void visitJetElement(@NotNull JetElement element) {
element.acceptChildren(this);
}
private static void putBackingFieldAnnotation(@NotNull AnnotationHolder holder, @NotNull JetNamedDeclaration element) {
PsiElement nameIdentifier = element.getNameIdentifier();
if (nameIdentifier != null) {
holder.createInfoAnnotation(
nameIdentifier,
"This property has a backing field")
.setTextAttributes(JetHighlightingColors.INSTANCE_PROPERTY_WITH_BACKING_FIELD);
}
}
}
@@ -133,9 +133,14 @@ public class JetColorSettingsPage implements ColorSettingsPage {
new AttributesDescriptor("Read-only local variable (val)", JetHighlightingColors.LOCAL_VAL),
new AttributesDescriptor("Mutable local variable (var)", JetHighlightingColors.LOCAL_VAR),
new AttributesDescriptor("Instance property", JetHighlightingColors.INSTANCE_PROPERTY),
new AttributesDescriptor("Instance property with backing field", JetHighlightingColors.INSTANCE_PROPERTY_WITH_BACKING_FIELD),
new AttributesDescriptor("Instance property backing field access", JetHighlightingColors.INSTANCE_BACKING_FIELD_ACCESS),
new AttributesDescriptor("Namespace property", JetHighlightingColors.NAMESPACE_PROPERTY),
new AttributesDescriptor("Namespace property with backing field", JetHighlightingColors.NAMESPACE_PROPERTY_WITH_BACKING_FIELD),
new AttributesDescriptor("Namespace property backing field access", JetHighlightingColors.NAMESPACE_BACKING_FIELD_ACCESS),
new AttributesDescriptor("Function literal default parameter", JetHighlightingColors.FUNCTION_LITERAL_DEFAULT_PARAMETER),
new AttributesDescriptor(OptionsBundle.message("options.java.attribute.descriptor.bad.character"), JetHighlightingColors.BAD_CHARACTER),
@@ -56,7 +56,6 @@ public class JetHighlighter extends SyntaxHighlighterBase {
keys1.put(JetTokens.AS_SAFE, JetHighlightingColors.KEYWORD);
keys1.put(JetTokens.LABEL_IDENTIFIER, JetHighlightingColors.LABEL);
keys1.put(JetTokens.ATAT, JetHighlightingColors.LABEL);
keys1.put(JetTokens.FIELD_IDENTIFIER, JetHighlightingColors.INSTANCE_BACKING_FIELD_ACCESS);
keys1.put(JetTokens.INTEGER_LITERAL, JetHighlightingColors.NUMBER);
keys1.put(JetTokens.FLOAT_LITERAL, JetHighlightingColors.NUMBER);
@@ -176,9 +176,17 @@ public class JetHighlightingColors {
CodeInsightColors.IMPLICIT_ANONYMOUS_CLASS_PARAMETER_ATTRIBUTES.getDefaultAttributes()
);
public static final TextAttributesKey INSTANCE_PROPERTY = TextAttributesKey.createTextAttributesKey(
"KOTLIN_INSTANCE_PROPERTY",
CodeInsightColors.INSTANCE_FIELD_ATTRIBUTES.getDefaultAttributes()
);
public static final TextAttributesKey INSTANCE_PROPERTY_WITH_BACKING_FIELD = TextAttributesKey.createTextAttributesKey(
"KOTLIN_INSTANCE_PROPERTY_WITH_BACKING_FIELD",
CodeInsightColors.INSTANCE_FIELD_ATTRIBUTES.getDefaultAttributes()
TextAttributes
.fromFlyweight(CodeInsightColors.INSTANCE_FIELD_ATTRIBUTES.getDefaultAttributes()
.getFlyweight().withEffectType(EffectType.BOLD_DOTTED_LINE).withEffectColor(
CodeInsightColors.INSTANCE_FIELD_ATTRIBUTES.getDefaultAttributes().getForegroundColor()))
);
public static final TextAttributesKey INSTANCE_BACKING_FIELD_ACCESS = TextAttributesKey.createTextAttributesKey(
@@ -186,6 +194,22 @@ public class JetHighlightingColors {
CodeInsightColors.INSTANCE_FIELD_ATTRIBUTES.getDefaultAttributes()
);
public static final TextAttributesKey NAMESPACE_PROPERTY = TextAttributesKey.createTextAttributesKey(
"KOTLIN_NAMESPACE_PROPERTY",
CodeInsightColors.STATIC_FIELD_ATTRIBUTES.getDefaultAttributes()
);
public static final TextAttributesKey NAMESPACE_PROPERTY_WITH_BACKING_FIELD = TextAttributesKey.createTextAttributesKey(
"KOTLIN_NAMESPACE_PROPERTY_WITH_BACKING_FIELD",
TextAttributes.fromFlyweight(CodeInsightColors.STATIC_FIELD_ATTRIBUTES.getDefaultAttributes()
.getFlyweight().withEffectType(EffectType.BOLD_DOTTED_LINE).withEffectColor(
CodeInsightColors.STATIC_FIELD_ATTRIBUTES.getDefaultAttributes().getForegroundColor())) );
public static final TextAttributesKey NAMESPACE_BACKING_FIELD_ACCESS = TextAttributesKey.createTextAttributesKey(
"KOTLIN_NAMESPACE_BACKING_FIELD_ACCESS",
CodeInsightColors.INSTANCE_FIELD_ATTRIBUTES.getDefaultAttributes()
);
public static final TextAttributesKey FUNCTION_LITERAL_DEFAULT_PARAMETER = TextAttributesKey.createTextAttributesKey(
"KOTLIN_CLOSURE_DEFAULT_PARAMETER",
new TextAttributes(null, null, null, null, Font.BOLD)
@@ -203,7 +227,7 @@ public class JetHighlightingColors {
public static final TextAttributesKey LABEL = TextAttributesKey.createTextAttributesKey(
"KOTLIN_LABEL",
new TextAttributes(new Color(74, 134, 232), null, null, null, Font.PLAIN)
new TextAttributes(new Color(0x4a86e8), null, null, null, Font.PLAIN)
);
public static final TextAttributesKey DEBUG_INFO = TextAttributesKey.createTextAttributesKey(
@@ -65,7 +65,7 @@ public class JetPsiChecker implements Annotator {
private static HighlightingVisitor[] getAfterAnalysisVisitor(AnnotationHolder holder, BindingContext bindingContext) {
return new AfterAnalysisHighlightingVisitor[]{
new BackingFieldHighlightingVisitor(holder, bindingContext),
new PropertiesHighlightingVisitor(holder, bindingContext),
new VariablesHighlightingVisitor(holder, bindingContext),
};
}
@@ -0,0 +1,95 @@
/*
* Copyright 2010-2012 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 org.jetbrains.jet.plugin.highlighter;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lexer.JetTokens;
class PropertiesHighlightingVisitor extends AfterAnalysisHighlightingVisitor {
PropertiesHighlightingVisitor(AnnotationHolder holder, BindingContext bindingContext) {
super(holder, bindingContext);
}
@Override
public void visitSimpleNameExpression(JetSimpleNameExpression expression) {
// TODO highlight extension properties
DeclarationDescriptor target = bindingContext.get(BindingContext.REFERENCE_TARGET, expression);
if (!(target instanceof PropertyDescriptor)) {
return;
}
boolean namespace = target.getContainingDeclaration() instanceof NamespaceDescriptor;
if (expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
holder.createInfoAnnotation(expression, null).setTextAttributes(
(namespace ?
JetHighlightingColors.NAMESPACE_BACKING_FIELD_ACCESS :
JetHighlightingColors.INSTANCE_BACKING_FIELD_ACCESS)
);
} else {
putPropertyAnnotation(expression, namespace, false);
}
}
@Override
public void visitProperty(@NotNull JetProperty property) {
PsiElement nameIdentifier = property.getNameIdentifier();
if (nameIdentifier == null) return;
VariableDescriptor propertyDescriptor = bindingContext.get(BindingContext.VARIABLE, property);
if (propertyDescriptor instanceof PropertyDescriptor) {
Boolean backingFieldRequired = bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor)propertyDescriptor);
boolean namespace = propertyDescriptor.getContainingDeclaration() instanceof NamespaceDescriptor;
putPropertyAnnotation(nameIdentifier, namespace, Boolean.TRUE.equals(backingFieldRequired));
}
}
@Override
public void visitParameter(@NotNull JetParameter parameter) {
PsiElement nameIdentifier = parameter.getNameIdentifier();
if (nameIdentifier == null) return;
PropertyDescriptor propertyDescriptor = bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter);
if (propertyDescriptor != null) {
Boolean backingFieldRequired = bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor);
putPropertyAnnotation(nameIdentifier, false, Boolean.TRUE.equals(backingFieldRequired));
}
}
@Override
public void visitJetElement(@NotNull JetElement element) {
element.acceptChildren(this);
}
private void putPropertyAnnotation(@NotNull PsiElement elementToHighlight, boolean namespace, boolean withBackingField) {
holder.createInfoAnnotation(
elementToHighlight,
"This property has a backing field")
.setTextAttributes(withBackingField ?
(namespace
? JetHighlightingColors.NAMESPACE_PROPERTY_WITH_BACKING_FIELD
: JetHighlightingColors.INSTANCE_PROPERTY_WITH_BACKING_FIELD) :
(namespace
? JetHighlightingColors.NAMESPACE_PROPERTY
: JetHighlightingColors.INSTANCE_PROPERTY));
}
}