HighlighterExtension can provide custom highlighting for calls
This commit is contained in:
+21
-30
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.idea.highlighter
|
package org.jetbrains.kotlin.idea.highlighter
|
||||||
|
|
||||||
import com.intellij.lang.annotation.AnnotationHolder
|
import com.intellij.lang.annotation.AnnotationHolder
|
||||||
|
import com.intellij.openapi.extensions.Extensions
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
|
import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
@@ -31,6 +32,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
|||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic
|
import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||||
|
|
||||||
internal class FunctionsHighlightingVisitor(holder: AnnotationHolder, bindingContext: BindingContext) :
|
internal class FunctionsHighlightingVisitor(holder: AnnotationHolder, bindingContext: BindingContext) :
|
||||||
AfterAnalysisHighlightingVisitor(holder, bindingContext) {
|
AfterAnalysisHighlightingVisitor(holder, bindingContext) {
|
||||||
@@ -73,37 +75,26 @@ internal class FunctionsHighlightingVisitor(holder: AnnotationHolder, bindingCon
|
|||||||
private fun highlightCall(callee: PsiElement, resolvedCall: ResolvedCall<out CallableDescriptor>) {
|
private fun highlightCall(callee: PsiElement, resolvedCall: ResolvedCall<out CallableDescriptor>) {
|
||||||
val calleeDescriptor = resolvedCall.resultingDescriptor
|
val calleeDescriptor = resolvedCall.resultingDescriptor
|
||||||
|
|
||||||
if (applyHighlighterExtensions(callee, calleeDescriptor)) return
|
val key = Extensions.getExtensions(HighlighterExtension.EP_NAME).firstNotNullResult { extension ->
|
||||||
|
extension.highlightCall(callee, resolvedCall)
|
||||||
if (calleeDescriptor.isDynamic()) {
|
} ?: when {
|
||||||
highlightName(callee, DYNAMIC_FUNCTION_CALL)
|
calleeDescriptor.isDynamic() -> DYNAMIC_FUNCTION_CALL
|
||||||
}
|
resolvedCall is VariableAsFunctionResolvedCall -> {
|
||||||
else if (resolvedCall is VariableAsFunctionResolvedCall) {
|
val container = calleeDescriptor.containingDeclaration
|
||||||
val container = calleeDescriptor.containingDeclaration
|
val containedInFunctionClassOrSubclass = container is ClassDescriptor && container.defaultType.isFunctionTypeOrSubtype
|
||||||
val containedInFunctionClassOrSubclass = container is ClassDescriptor && container.defaultType.isFunctionTypeOrSubtype
|
if (containedInFunctionClassOrSubclass)
|
||||||
highlightName(callee, if (containedInFunctionClassOrSubclass)
|
VARIABLE_AS_FUNCTION_CALL
|
||||||
VARIABLE_AS_FUNCTION_CALL
|
else
|
||||||
else
|
VARIABLE_AS_FUNCTION_LIKE_CALL
|
||||||
VARIABLE_AS_FUNCTION_LIKE_CALL)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (calleeDescriptor is ConstructorDescriptor) {
|
|
||||||
highlightName(callee, CONSTRUCTOR_CALL)
|
|
||||||
}
|
|
||||||
else if (calleeDescriptor is FunctionDescriptor) {
|
|
||||||
val attributesKey = when {
|
|
||||||
calleeDescriptor.extensionReceiverParameter != null ->
|
|
||||||
EXTENSION_FUNCTION_CALL
|
|
||||||
|
|
||||||
DescriptorUtils.isTopLevelDeclaration(calleeDescriptor) ->
|
|
||||||
PACKAGE_FUNCTION_CALL
|
|
||||||
|
|
||||||
else ->
|
|
||||||
FUNCTION_CALL
|
|
||||||
}
|
|
||||||
|
|
||||||
highlightName(callee, attributesKey)
|
|
||||||
}
|
}
|
||||||
|
calleeDescriptor is ConstructorDescriptor -> CONSTRUCTOR_CALL
|
||||||
|
calleeDescriptor !is FunctionDescriptor -> null
|
||||||
|
calleeDescriptor.extensionReceiverParameter != null -> EXTENSION_FUNCTION_CALL
|
||||||
|
DescriptorUtils.isTopLevelDeclaration(calleeDescriptor) -> PACKAGE_FUNCTION_CALL
|
||||||
|
else -> FUNCTION_CALL
|
||||||
|
}
|
||||||
|
if (key != null) {
|
||||||
|
highlightName(callee, key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -20,9 +20,13 @@ import com.intellij.openapi.editor.colors.TextAttributesKey
|
|||||||
import com.intellij.openapi.extensions.ExtensionPointName
|
import com.intellij.openapi.extensions.ExtensionPointName
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
|
|
||||||
abstract class HighlighterExtension {
|
abstract class HighlighterExtension {
|
||||||
abstract fun highlightReference(elementToHighlight: PsiElement, descriptor: DeclarationDescriptor): TextAttributesKey?
|
abstract fun highlightDeclaration(elementToHighlight: PsiElement, descriptor: DeclarationDescriptor): TextAttributesKey?
|
||||||
|
|
||||||
|
open fun highlightCall(elementToHighlight: PsiElement, resolvedCall: ResolvedCall<*>): TextAttributesKey?
|
||||||
|
= highlightDeclaration(elementToHighlight, resolvedCall.resultingDescriptor)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val EP_NAME = ExtensionPointName.create<HighlighterExtension>("org.jetbrains.kotlin.highlighterExtension")
|
val EP_NAME = ExtensionPointName.create<HighlighterExtension>("org.jetbrains.kotlin.highlighterExtension")
|
||||||
|
|||||||
+11
-9
@@ -24,16 +24,17 @@ import com.intellij.openapi.util.TextRange
|
|||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.psi.KtVisitorVoid
|
import org.jetbrains.kotlin.psi.KtVisitorVoid
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||||
|
|
||||||
abstract class HighlightingVisitor protected constructor(
|
abstract class HighlightingVisitor protected constructor(
|
||||||
private val holder: AnnotationHolder
|
private val holder: AnnotationHolder
|
||||||
) : KtVisitorVoid() {
|
) : KtVisitorVoid() {
|
||||||
|
|
||||||
protected fun createInfoAnnotation(element: PsiElement, message: String? = null): Annotation =
|
protected fun createInfoAnnotation(element: PsiElement, message: String? = null): Annotation =
|
||||||
createInfoAnnotation(element.textRange, message)
|
createInfoAnnotation(element.textRange, message)
|
||||||
|
|
||||||
protected fun createInfoAnnotation(textRange: TextRange, message: String? = null): Annotation =
|
protected fun createInfoAnnotation(textRange: TextRange, message: String? = null): Annotation =
|
||||||
holder.createInfoAnnotation(textRange, message)
|
holder.createInfoAnnotation(textRange, message)
|
||||||
|
|
||||||
protected fun highlightName(element: PsiElement, attributesKey: TextAttributesKey, message: String? = null) {
|
protected fun highlightName(element: PsiElement, attributesKey: TextAttributesKey, message: String? = null) {
|
||||||
if (NameHighlighter.namesHighlightingEnabled && !element.textRange.isEmpty) {
|
if (NameHighlighter.namesHighlightingEnabled && !element.textRange.isEmpty) {
|
||||||
@@ -49,13 +50,14 @@ abstract class HighlightingVisitor protected constructor(
|
|||||||
|
|
||||||
protected fun applyHighlighterExtensions(element: PsiElement, descriptor: DeclarationDescriptor): Boolean {
|
protected fun applyHighlighterExtensions(element: PsiElement, descriptor: DeclarationDescriptor): Boolean {
|
||||||
if (!NameHighlighter.namesHighlightingEnabled) return false
|
if (!NameHighlighter.namesHighlightingEnabled) return false
|
||||||
for (extension in Extensions.getExtensions(HighlighterExtension.EP_NAME)) {
|
|
||||||
val key = extension.highlightReference(element, descriptor)
|
Extensions.getExtensions(HighlighterExtension.EP_NAME).firstNotNullResult { extension ->
|
||||||
if (key != null) {
|
extension.highlightDeclaration(element, descriptor)
|
||||||
highlightName(element, key)
|
}?.let { key ->
|
||||||
return true
|
highlightName(element, key)
|
||||||
}
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.android
|
package org.jetbrains.kotlin.android
|
||||||
|
|
||||||
import com.intellij.openapi.editor.colors.TextAttributesKey
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.android.synthetic.res.AndroidSyntheticProperty
|
import org.jetbrains.kotlin.android.synthetic.res.AndroidSyntheticProperty
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
@@ -24,9 +23,11 @@ import org.jetbrains.kotlin.idea.highlighter.HighlighterExtension
|
|||||||
import org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingColors
|
import org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingColors
|
||||||
|
|
||||||
class AndroidHighlighterExtension : HighlighterExtension() {
|
class AndroidHighlighterExtension : HighlighterExtension() {
|
||||||
override fun highlightReference(elementToHighlight: PsiElement, descriptor: DeclarationDescriptor): TextAttributesKey? =
|
override fun highlightDeclaration(
|
||||||
if (descriptor is AndroidSyntheticProperty)
|
elementToHighlight: PsiElement,
|
||||||
KotlinHighlightingColors.ANDROID_EXTENSIONS_PROPERTY_CALL
|
descriptor: DeclarationDescriptor
|
||||||
else
|
) = when (descriptor) {
|
||||||
null
|
is AndroidSyntheticProperty -> KotlinHighlightingColors.ANDROID_EXTENSIONS_PROPERTY_CALL
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user