Added separate highlighting keys for variables invoked as function and function-like.

This commit is contained in:
Evgeny Gerashchenko
2013-04-03 20:32:12 +04:00
parent a6293e10d9
commit f53af70ad6
5 changed files with 77 additions and 24 deletions
@@ -116,6 +116,7 @@ options.jet.attribute.descriptor.namespace.fun.call=Package-level function call
options.jet.attribute.descriptor.extension.fun.call=Extension function call
options.jet.attribute.descriptor.constructor.call=Constructor call
options.jet.attribute.descriptor.variable.as.function.call=Variable as function call
options.jet.attribute.descriptor.variable.as.function.like.call=Variable as function-like call
options.jet.attribute.descriptor.auto.casted=Smart-cast value
options.jet.attribute.descriptor.label=Label
change.to.function.invocation=Change to function invocation
@@ -22,6 +22,11 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
public class FunctionsHighlightingVisitor extends AfterAnalysisHighlightingVisitor {
public FunctionsHighlightingVisitor(AnnotationHolder holder, BindingContext bindingContext) {
@@ -58,33 +63,72 @@ public class FunctionsHighlightingVisitor extends AfterAnalysisHighlightingVisit
public void visitCallExpression(JetCallExpression expression) {
JetExpression callee = expression.getCalleeExpression();
if (callee instanceof JetReferenceExpression) {
DeclarationDescriptor calleeDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, (JetReferenceExpression)callee);
if (calleeDescriptor != null) {
if (calleeDescriptor instanceof ConstructorDescriptor) {
JetPsiChecker.highlightName(holder, callee, JetHighlightingColors.CONSTRUCTOR_CALL);
ResolvedCall<? extends CallableDescriptor> resolvedCall =
bindingContext.get(BindingContext.RESOLVED_CALL, (JetReferenceExpression) callee);
if (resolvedCall != null) {
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
highlightVariableAsFunctionCall(callee, (VariableAsFunctionResolvedCall) resolvedCall);
}
else if (calleeDescriptor instanceof FunctionDescriptor) {
FunctionDescriptor fun = (FunctionDescriptor)calleeDescriptor;
JetPsiChecker.highlightName(holder, callee, JetHighlightingColors.FUNCTION_CALL);
if (DescriptorUtils.isTopLevelDeclaration(fun)) {
JetPsiChecker.highlightName(holder, callee, JetHighlightingColors.NAMESPACE_FUNCTION_CALL);
else {
DeclarationDescriptor calleeDescriptor = resolvedCall.getResultingDescriptor();
if (calleeDescriptor instanceof ConstructorDescriptor) {
JetPsiChecker.highlightName(holder, callee, JetHighlightingColors.CONSTRUCTOR_CALL);
}
if (fun.getReceiverParameter() != null) {
JetPsiChecker.highlightName(holder, callee, JetHighlightingColors.EXTENSION_FUNCTION_CALL);
else if (calleeDescriptor instanceof FunctionDescriptor) {
FunctionDescriptor fun = (FunctionDescriptor) calleeDescriptor;
JetPsiChecker.highlightName(holder, callee, JetHighlightingColors.FUNCTION_CALL);
if (DescriptorUtils.isTopLevelDeclaration(fun)) {
JetPsiChecker.highlightName(holder, callee, JetHighlightingColors.NAMESPACE_FUNCTION_CALL);
}
if (fun.getReceiverParameter() != null) {
JetPsiChecker.highlightName(holder, callee, JetHighlightingColors.EXTENSION_FUNCTION_CALL);
}
}
}
else if (calleeDescriptor instanceof VariableDescriptor) {
String kind = calleeDescriptor instanceof ValueParameterDescriptor
? "parameter"
: calleeDescriptor instanceof PropertyDescriptor
? "property"
: "variable";
holder.createInfoAnnotation(callee, "Calling " + kind + " as function").setTextAttributes(
JetHighlightingColors.VARIABLE_AS_FUNCTION_CALL);
}
}
}
super.visitCallExpression(expression);
}
private void highlightVariableAsFunctionCall(JetExpression callee, VariableAsFunctionResolvedCall resolvedCall) {
VariableDescriptor variableDescriptor = resolvedCall.getVariableCall().getResultingDescriptor();
String kind = variableDescriptor instanceof ValueParameterDescriptor
? "parameter"
: variableDescriptor instanceof PropertyDescriptor
? "property"
: "variable";
if (containedInFunctionClassOrSubclass(resolvedCall.getFunctionCall().getResultingDescriptor())) {
holder.createInfoAnnotation(callee, "Calling " + kind + " as function").setTextAttributes(
JetHighlightingColors.VARIABLE_AS_FUNCTION_CALL);
}
else {
holder.createInfoAnnotation(callee, "Calling " + kind + " as function-like").setTextAttributes(
JetHighlightingColors.VARIABLE_AS_FUNCTION_LIKE_CALL);
}
}
private static boolean containedInFunctionClassOrSubclass(DeclarationDescriptor calleeDescriptor) {
DeclarationDescriptor parent = calleeDescriptor.getContainingDeclaration();
if (!(parent instanceof ClassDescriptor)) {
return false;
}
KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
JetType defaultType = ((ClassDescriptor) parent).getDefaultType();
if (builtIns.isFunctionOrExtensionFunctionType(defaultType)) {
return true;
}
for (JetType supertype : TypeUtils.getAllSupertypes(defaultType)) {
if (builtIns.isFunctionOrExtensionFunctionType(supertype)) {
return true;
}
}
return false;
}
}
@@ -58,10 +58,10 @@ public class JetColorSettingsPage implements ColorSettingsPage {
" */\n" +
"[<ANNOTATION>Deprecated</ANNOTATION>]\n" +
"<BUILTIN_ANNOTATION>public</BUILTIN_ANNOTATION> class <CLASS>MyClass</CLASS><<BUILTIN_ANNOTATION>out</BUILTIN_ANNOTATION> <TYPE_PARAMETER>T</TYPE_PARAMETER> : <TRAIT>Iterable</TRAIT><<TYPE_PARAMETER>T</TYPE_PARAMETER>>>(var <INSTANCE_PROPERTY><MUTABLE_VARIABLE>prop1</MUTABLE_VARIABLE></INSTANCE_PROPERTY> : Int) {\n" +
" fun <FUNCTION_DECLARATION>foo</FUNCTION_DECLARATION>(<PARAMETER>nullable</PARAMETER> : String?, <PARAMETER>r</PARAMETER> : <TRAIT>Runnable</TRAIT>, <PARAMETER>f</PARAMETER> : () -> Int) {\n" +
" fun <FUNCTION_DECLARATION>foo</FUNCTION_DECLARATION>(<PARAMETER>nullable</PARAMETER> : String?, <PARAMETER>r</PARAMETER> : <TRAIT>Runnable</TRAIT>, <PARAMETER>f</PARAMETER> : () -> Int, <PARAMETER>fl</PARAMETER> : <TRAIT>FunctionLike</TRAIT>) {\n" +
" <FUNCTION_CALL><NAMESPACE_FUNCTION_CALL>println</NAMESPACE_FUNCTION_CALL></FUNCTION_CALL>(\"length\\nis ${<PARAMETER>nullable</PARAMETER><SAFE_ACCESS>?.</SAFE_ACCESS><INSTANCE_PROPERTY>length</INSTANCE_PROPERTY>} <INVALID_STRING_ESCAPE><STRING_ESCAPE>\\e</STRING_ESCAPE></INVALID_STRING_ESCAPE>\")\n" +
" val <LOCAL_VARIABLE>ints</LOCAL_VARIABLE> = java.util.<CONSTRUCTOR_CALL>ArrayList</CONSTRUCTOR_CALL><Int?>(2)\n" +
" <LOCAL_VARIABLE>ints</LOCAL_VARIABLE>[0] = 102 + <PARAMETER><VARIABLE_AS_FUNCTION_CALL>f</VARIABLE_AS_FUNCTION_CALL></PARAMETER>()\n" +
" <LOCAL_VARIABLE>ints</LOCAL_VARIABLE>[0] = 102 + <PARAMETER><VARIABLE_AS_FUNCTION_CALL>f</VARIABLE_AS_FUNCTION_CALL></PARAMETER>() + <PARAMETER><VARIABLE_AS_FUNCTION_LIKE_CALL>fl</VARIABLE_AS_FUNCTION_LIKE_CALL></PARAMETER>()\n" +
" val <LOCAL_VARIABLE>myFun</LOCAL_VARIABLE> = <FUNCTION_LITERAL_BRACES_AND_ARROW>{</FUNCTION_LITERAL_BRACES_AND_ARROW> <FUNCTION_LITERAL_BRACES_AND_ARROW>-></FUNCTION_LITERAL_BRACES_AND_ARROW> \"\" <FUNCTION_LITERAL_BRACES_AND_ARROW>}</FUNCTION_LITERAL_BRACES_AND_ARROW>;\n" +
" var <LOCAL_VARIABLE><MUTABLE_VARIABLE><WRAPPED_INTO_REF>ref</WRAPPED_INTO_REF></MUTABLE_VARIABLE></LOCAL_VARIABLE> = <LOCAL_VARIABLE>ints</LOCAL_VARIABLE>.<FUNCTION_CALL>size</FUNCTION_CALL>()\n" +
" if (!<LOCAL_VARIABLE>ints</LOCAL_VARIABLE>.<EXTENSION_PROPERTY><NAMESPACE_PROPERTY>empty</NAMESPACE_PROPERTY></EXTENSION_PROPERTY>) {\n" +
@@ -156,6 +156,7 @@ public class JetColorSettingsPage implements ColorSettingsPage {
new AttributesDescriptor(JetBundle.message("options.jet.attribute.descriptor.extension.fun.call"), JetHighlightingColors.EXTENSION_FUNCTION_CALL),
new AttributesDescriptor(JetBundle.message("options.jet.attribute.descriptor.constructor.call"), JetHighlightingColors.CONSTRUCTOR_CALL),
new AttributesDescriptor(JetBundle.message("options.jet.attribute.descriptor.variable.as.function.call"), JetHighlightingColors.VARIABLE_AS_FUNCTION_CALL),
new AttributesDescriptor(JetBundle.message("options.jet.attribute.descriptor.variable.as.function.like.call"), JetHighlightingColors.VARIABLE_AS_FUNCTION_LIKE_CALL),
new AttributesDescriptor(OptionsBundle.message("options.java.attribute.descriptor.bad.character"), JetHighlightingColors.BAD_CHARACTER),
@@ -241,6 +241,11 @@ public class JetHighlightingColors {
new TextAttributes()
);
public static final TextAttributesKey VARIABLE_AS_FUNCTION_LIKE_CALL = TextAttributesKey.createTextAttributesKey(
"KOTLIN_VARIABLE_AS_FUNCTION_LIKE",
new TextAttributes()
);
public static final TextAttributesKey BAD_CHARACTER = TextAttributesKey.createTextAttributesKey(
"KOTLIN_BAD_CHARACTER",
HighlighterColors.BAD_CHARACTER.getDefaultAttributes()
@@ -7,7 +7,7 @@ val <info>property</info> = {}
fun foo(param: (Int) -> Int, functionLike: FunctionLike) {
<info descr="Calling parameter as function">param</info>(1)
<info descr="Calling parameter as function">functionLike</info>()
<info descr="Calling parameter as function-like">functionLike</info>()
val v1 = param
var v2 = param
@@ -15,5 +15,7 @@ fun foo(param: (Int) -> Int, functionLike: FunctionLike) {
<info descr="Calling variable as function">v1</info>(1)
<info descr="Calling variable as function">v2</info>(1)
<info descr="Calling property as function">property</info>()
<info descr="Calling property as function">property</info>();
{}() //should not be highlighted as "calling variable as function"
}