Highlighting visitor: refactoring

Do not call AnnotationHolder functions directly,
only via HighlightingVisitor
This commit is contained in:
Mikhail Glukhikh
2017-06-08 19:13:36 +03:00
parent f225d8dea5
commit aa3589004e
7 changed files with 57 additions and 50 deletions
@@ -30,11 +30,10 @@ import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtExpressionWithLabel import org.jetbrains.kotlin.psi.KtExpressionWithLabel
import org.jetbrains.kotlin.psi.KtLambdaExpression import org.jetbrains.kotlin.psi.KtLambdaExpression
import org.jetbrains.kotlin.psi.KtValueArgument import org.jetbrains.kotlin.psi.KtValueArgument
import org.jetbrains.kotlin.psi.KtVisitorVoid
import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset
internal class BeforeResolveHighlightingVisitor(private val holder: AnnotationHolder) : KtVisitorVoid() { internal class BeforeResolveHighlightingVisitor(holder: AnnotationHolder) : HighlightingVisitor(holder) {
override fun visitElement(element: PsiElement) { override fun visitElement(element: PsiElement) {
val elementType = element.node.elementType val elementType = element.node.elementType
@@ -51,7 +50,7 @@ internal class BeforeResolveHighlightingVisitor(private val holder: AnnotationHo
else -> return else -> return
} }
holder.createInfoAnnotation(element, null).textAttributes = attributes createInfoAnnotation(element, null).textAttributes = attributes
} }
private fun willApplyRainbowHighlight(element: KDocLink): Boolean { private fun willApplyRainbowHighlight(element: KDocLink): Boolean {
@@ -66,29 +65,29 @@ internal class BeforeResolveHighlightingVisitor(private val holder: AnnotationHo
if (ApplicationManager.getApplication().isUnitTestMode) return if (ApplicationManager.getApplication().isUnitTestMode) return
val functionLiteral = lambdaExpression.functionLiteral val functionLiteral = lambdaExpression.functionLiteral
holder.createInfoAnnotation(functionLiteral.lBrace, null).textAttributes = KotlinHighlightingColors.FUNCTION_LITERAL_BRACES_AND_ARROW createInfoAnnotation(functionLiteral.lBrace, null).textAttributes = KotlinHighlightingColors.FUNCTION_LITERAL_BRACES_AND_ARROW
val closingBrace = functionLiteral.rBrace val closingBrace = functionLiteral.rBrace
if (closingBrace != null) { if (closingBrace != null) {
holder.createInfoAnnotation(closingBrace, null).textAttributes = KotlinHighlightingColors.FUNCTION_LITERAL_BRACES_AND_ARROW createInfoAnnotation(closingBrace, null).textAttributes = KotlinHighlightingColors.FUNCTION_LITERAL_BRACES_AND_ARROW
} }
val arrow = functionLiteral.arrow val arrow = functionLiteral.arrow
if (arrow != null) { if (arrow != null) {
holder.createInfoAnnotation(arrow, null).textAttributes = KotlinHighlightingColors.FUNCTION_LITERAL_BRACES_AND_ARROW createInfoAnnotation(arrow, null).textAttributes = KotlinHighlightingColors.FUNCTION_LITERAL_BRACES_AND_ARROW
} }
} }
override fun visitArgument(argument: KtValueArgument) { override fun visitArgument(argument: KtValueArgument) {
val argumentName = argument.getArgumentName() ?: return val argumentName = argument.getArgumentName() ?: return
val eq = argument.equalsToken ?: return val eq = argument.equalsToken ?: return
holder.createInfoAnnotation(TextRange(argumentName.startOffset, eq.endOffset), null).textAttributes = KotlinHighlightingColors.NAMED_ARGUMENT createInfoAnnotation(TextRange(argumentName.startOffset, eq.endOffset), null).textAttributes = KotlinHighlightingColors.NAMED_ARGUMENT
} }
override fun visitExpressionWithLabel(expression: KtExpressionWithLabel) { override fun visitExpressionWithLabel(expression: KtExpressionWithLabel) {
val targetLabel = expression.getTargetLabel() val targetLabel = expression.getTargetLabel()
if (targetLabel != null) { if (targetLabel != null) {
holder.highlightName(targetLabel, KotlinHighlightingColors.LABEL) highlightName(targetLabel, KotlinHighlightingColors.LABEL)
} }
} }
} }
@@ -36,7 +36,7 @@ internal class FunctionsHighlightingVisitor(holder: AnnotationHolder, bindingCon
AfterAnalysisHighlightingVisitor(holder, bindingContext) { AfterAnalysisHighlightingVisitor(holder, bindingContext) {
override fun visitNamedFunction(function: KtNamedFunction) { override fun visitNamedFunction(function: KtNamedFunction) {
function.nameIdentifier?.let { holder.highlightName(it, FUNCTION_DECLARATION) } function.nameIdentifier?.let { highlightName(it, FUNCTION_DECLARATION) }
super.visitNamedFunction(function) super.visitNamedFunction(function)
} }
@@ -45,7 +45,7 @@ internal class FunctionsHighlightingVisitor(holder: AnnotationHolder, bindingCon
val calleeExpression = call.calleeExpression val calleeExpression = call.calleeExpression
val typeElement = calleeExpression.typeReference?.typeElement val typeElement = calleeExpression.typeReference?.typeElement
if (typeElement is KtUserType) { if (typeElement is KtUserType) {
typeElement.referenceExpression?.let { holder.highlightName(it, CONSTRUCTOR_CALL) } typeElement.referenceExpression?.let { highlightName(it, CONSTRUCTOR_CALL) }
} }
super.visitSuperTypeCallEntry(call) super.visitSuperTypeCallEntry(call)
} }
@@ -74,19 +74,19 @@ internal class FunctionsHighlightingVisitor(holder: AnnotationHolder, bindingCon
val calleeDescriptor = resolvedCall.resultingDescriptor val calleeDescriptor = resolvedCall.resultingDescriptor
if (calleeDescriptor.isDynamic()) { if (calleeDescriptor.isDynamic()) {
holder.highlightName(callee, DYNAMIC_FUNCTION_CALL) highlightName(callee, DYNAMIC_FUNCTION_CALL)
} }
else if (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
holder.highlightName(callee, 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 { else {
if (calleeDescriptor is ConstructorDescriptor) { if (calleeDescriptor is ConstructorDescriptor) {
holder.highlightName(callee, CONSTRUCTOR_CALL) highlightName(callee, CONSTRUCTOR_CALL)
} }
else if (calleeDescriptor is FunctionDescriptor) { else if (calleeDescriptor is FunctionDescriptor) {
val attributesKey = when { val attributesKey = when {
@@ -100,7 +100,7 @@ internal class FunctionsHighlightingVisitor(holder: AnnotationHolder, bindingCon
FUNCTION_CALL FUNCTION_CALL
} }
holder.highlightName(callee, attributesKey) highlightName(callee, attributesKey)
} }
} }
} }
@@ -16,7 +16,30 @@
package org.jetbrains.kotlin.idea.highlighter package org.jetbrains.kotlin.idea.highlighter
import com.intellij.lang.annotation.Annotation
import com.intellij.lang.annotation.AnnotationHolder import com.intellij.lang.annotation.AnnotationHolder
import com.intellij.openapi.editor.colors.TextAttributesKey
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.psi.KtVisitorVoid import org.jetbrains.kotlin.psi.KtVisitorVoid
abstract class HighlightingVisitor protected constructor(protected var holder: AnnotationHolder) : KtVisitorVoid() abstract class HighlightingVisitor protected constructor(private var holder: AnnotationHolder) : KtVisitorVoid() {
protected fun createInfoAnnotation(element: PsiElement, message: String? = null): Annotation =
createInfoAnnotation(element.textRange, message)
protected fun createInfoAnnotation(textRange: TextRange, message: String? = null): Annotation =
holder.createInfoAnnotation(textRange, message)
protected fun highlightName(element: PsiElement, attributesKey: TextAttributesKey, message: String? = null) {
if (NameHighlighter.namesHighlightingEnabled) {
createInfoAnnotation(element, message).textAttributes = attributesKey
}
}
protected fun highlightName(textRange: TextRange, attributesKey: TextAttributesKey, message: String? = null) {
if (NameHighlighter.namesHighlightingEnabled) {
createInfoAnnotation(textRange, message).textAttributes = attributesKey
}
}
}
@@ -16,10 +16,6 @@
package org.jetbrains.kotlin.idea.highlighter package org.jetbrains.kotlin.idea.highlighter
import com.intellij.lang.annotation.AnnotationHolder
import com.intellij.openapi.editor.colors.TextAttributesKey
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import org.jetbrains.annotations.TestOnly import org.jetbrains.annotations.TestOnly
object NameHighlighter { object NameHighlighter {
@@ -27,14 +23,3 @@ object NameHighlighter {
@TestOnly set @TestOnly set
} }
fun AnnotationHolder.highlightName(element: PsiElement, attributesKey: TextAttributesKey) {
if (NameHighlighter.namesHighlightingEnabled) {
createInfoAnnotation(element, null).textAttributes = attributesKey
}
}
fun AnnotationHolder.highlightName(textRange: TextRange, attributesKey: TextAttributesKey) {
if (NameHighlighter.namesHighlightingEnabled) {
createInfoAnnotation(textRange, null).textAttributes = attributesKey
}
}
@@ -38,7 +38,7 @@ internal class PropertiesHighlightingVisitor(holder: AnnotationHolder, bindingCo
} }
val target = bindingContext.get(BindingContext.REFERENCE_TARGET, expression) val target = bindingContext.get(BindingContext.REFERENCE_TARGET, expression)
if (target is SyntheticFieldDescriptor) { if (target is SyntheticFieldDescriptor) {
holder.highlightName(expression, BACKING_FIELD_VARIABLE) highlightName(expression, BACKING_FIELD_VARIABLE)
return return
} }
if (target !is PropertyDescriptor) { if (target !is PropertyDescriptor) {
@@ -85,6 +85,6 @@ internal class PropertiesHighlightingVisitor(holder: AnnotationHolder, bindingCo
else -> else ->
INSTANCE_PROPERTY INSTANCE_PROPERTY
} }
holder.highlightName(elementToHighlight, attributesKey) highlightName(elementToHighlight, attributesKey)
} }
} }
@@ -51,11 +51,11 @@ internal class TypeKindHighlightingVisitor(holder: AnnotationHolder, bindingCont
highlightAnnotation(expression) highlightAnnotation(expression)
} }
else { else {
holder.highlightName(expression, textAttributesKeyForClass(referenceTarget)) highlightName(expression, textAttributesKeyForClass(referenceTarget))
} }
} }
else if (referenceTarget is TypeParameterDescriptor) { else if (referenceTarget is TypeParameterDescriptor) {
holder.highlightName(expression, TYPE_PARAMETER) highlightName(expression, TYPE_PARAMETER)
} }
} }
} }
@@ -74,11 +74,11 @@ internal class TypeKindHighlightingVisitor(holder: AnnotationHolder, bindingCont
} }
} }
holder.highlightName(range, ANNOTATION) highlightName(range, ANNOTATION)
} }
override fun visitTypeParameter(parameter: KtTypeParameter) { override fun visitTypeParameter(parameter: KtTypeParameter) {
parameter.nameIdentifier?.let { holder.highlightName(it, TYPE_PARAMETER) } parameter.nameIdentifier?.let { highlightName(it, TYPE_PARAMETER) }
super.visitTypeParameter(parameter) super.visitTypeParameter(parameter)
} }
@@ -86,7 +86,7 @@ internal class TypeKindHighlightingVisitor(holder: AnnotationHolder, bindingCont
val identifier = classOrObject.nameIdentifier val identifier = classOrObject.nameIdentifier
val classDescriptor = bindingContext.get(BindingContext.CLASS, classOrObject) val classDescriptor = bindingContext.get(BindingContext.CLASS, classOrObject)
if (identifier != null && classDescriptor != null) { if (identifier != null && classDescriptor != null) {
holder.highlightName(identifier, textAttributesKeyForClass(classDescriptor)) highlightName(identifier, textAttributesKeyForClass(classDescriptor))
} }
super.visitClassOrObject(classOrObject) super.visitClassOrObject(classOrObject)
} }
@@ -42,7 +42,7 @@ internal class VariablesHighlightingVisitor(holder: AnnotationHolder, bindingCon
val target = bindingContext.get(REFERENCE_TARGET, expression) ?: return val target = bindingContext.get(REFERENCE_TARGET, expression) ?: return
if (target is ValueParameterDescriptor) { if (target is ValueParameterDescriptor) {
if (bindingContext.get(AUTO_CREATED_IT, target) == true) { if (bindingContext.get(AUTO_CREATED_IT, target) == true) {
holder.createInfoAnnotation(expression, "Automatically declared based on the expected type") createInfoAnnotation(expression, "Automatically declared based on the expected type")
.textAttributes = FUNCTION_LITERAL_DEFAULT_PARAMETER .textAttributes = FUNCTION_LITERAL_DEFAULT_PARAMETER
} }
} }
@@ -89,15 +89,15 @@ internal class VariablesHighlightingVisitor(holder: AnnotationHolder, bindingCon
is ImplicitClassReceiver -> "Implicit receiver" is ImplicitClassReceiver -> "Implicit receiver"
else -> "Unknown receiver" else -> "Unknown receiver"
} }
holder.createInfoAnnotation(expression, createInfoAnnotation(expression,
"$receiverName smart cast to " + DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(type)) "$receiverName smart cast to " + DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(type))
.textAttributes = SMART_CAST_RECEIVER .textAttributes = SMART_CAST_RECEIVER
} }
} }
val nullSmartCast = bindingContext.get(SMARTCAST_NULL, expression) == true val nullSmartCast = bindingContext.get(SMARTCAST_NULL, expression) == true
if (nullSmartCast) { if (nullSmartCast) {
holder.createInfoAnnotation(expression, "Always null") createInfoAnnotation(expression, "Always null")
.textAttributes = SMART_CONSTANT .textAttributes = SMART_CONSTANT
} }
@@ -105,14 +105,14 @@ internal class VariablesHighlightingVisitor(holder: AnnotationHolder, bindingCon
if (smartCast != null) { if (smartCast != null) {
val defaultType = smartCast.defaultType val defaultType = smartCast.defaultType
if (defaultType != null) { if (defaultType != null) {
holder.createInfoAnnotation(getSmartCastTarget(expression), createInfoAnnotation(getSmartCastTarget(expression),
"Smart cast to " + DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(defaultType)) "Smart cast to " + DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(defaultType))
.textAttributes = SMART_CAST_VALUE .textAttributes = SMART_CAST_VALUE
} }
else if (smartCast is MultipleSmartCasts) { else if (smartCast is MultipleSmartCasts) {
for ((call, type) in smartCast.map) { for ((call, type) in smartCast.map) {
holder.createInfoAnnotation(getSmartCastTarget(expression), createInfoAnnotation(getSmartCastTarget(expression),
"Smart cast to ${DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(type)} (for $call call)") "Smart cast to ${DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(type)} (for $call call)")
.textAttributes = SMART_CAST_VALUE .textAttributes = SMART_CAST_VALUE
} }
} }
@@ -133,12 +133,12 @@ internal class VariablesHighlightingVisitor(holder: AnnotationHolder, bindingCon
if (descriptor is VariableDescriptor) { if (descriptor is VariableDescriptor) {
if (descriptor.isDynamic()) { if (descriptor.isDynamic()) {
holder.highlightName(elementToHighlight, DYNAMIC_PROPERTY_CALL) highlightName(elementToHighlight, DYNAMIC_PROPERTY_CALL)
return return
} }
if (descriptor.isVar) { if (descriptor.isVar) {
holder.highlightName(elementToHighlight, MUTABLE_VARIABLE) highlightName(elementToHighlight, MUTABLE_VARIABLE)
} }
if (bindingContext.get(CAPTURED_IN_CLOSURE, descriptor) == CaptureKind.NOT_INLINE) { if (bindingContext.get(CAPTURED_IN_CLOSURE, descriptor) == CaptureKind.NOT_INLINE) {
@@ -149,16 +149,16 @@ internal class VariablesHighlightingVisitor(holder: AnnotationHolder, bindingCon
val parent = elementToHighlight.parent val parent = elementToHighlight.parent
if (!(parent is PsiNameIdentifierOwner && parent.nameIdentifier == elementToHighlight)) { if (!(parent is PsiNameIdentifierOwner && parent.nameIdentifier == elementToHighlight)) {
holder.createInfoAnnotation(elementToHighlight, msg).textAttributes = WRAPPED_INTO_REF createInfoAnnotation(elementToHighlight, msg).textAttributes = WRAPPED_INTO_REF
} }
} }
if (descriptor is LocalVariableDescriptor && descriptor !is SyntheticFieldDescriptor) { if (descriptor is LocalVariableDescriptor && descriptor !is SyntheticFieldDescriptor) {
holder.highlightName(elementToHighlight, LOCAL_VARIABLE) highlightName(elementToHighlight, LOCAL_VARIABLE)
} }
if (descriptor is ValueParameterDescriptor) { if (descriptor is ValueParameterDescriptor) {
holder.highlightName(elementToHighlight, PARAMETER) highlightName(elementToHighlight, PARAMETER)
} }
} }
} }