[Java. Logging] Implement simple logic for Logging placeholder annotator

IDEA-342483

GitOrigin-RevId: 009a594b4e80011599b846580d89ce4097149b6f
This commit is contained in:
Georgii Ustinov
2024-03-22 21:32:09 +02:00
committed by intellij-monorepo-bot
parent faf35d0309
commit 7efc1956d2
3 changed files with 70 additions and 18 deletions

View File

@@ -181,6 +181,8 @@
<inspectionCustomComponent implementation="com.intellij.codeInsight.options.JavaInspectionButtons"/>
<annotator language="UAST" implementationClass="com.intellij.analysis.logging.highlighting.LoggingPlaceholderAnnotator"/>
<psi.symbolReferenceProvider
hostElementClass="com.intellij.model.psi.PsiExternalReferenceHost"
hostLanguage="UAST"

View File

@@ -0,0 +1,46 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.analysis.logging.highlighting
import com.intellij.analysis.logging.resolve.getAlignedPlaceholderCount
import com.intellij.analysis.logging.resolve.getContext
import com.intellij.analysis.logging.resolve.getPlaceholderRanges
import com.intellij.lang.annotation.AnnotationHolder
import com.intellij.lang.annotation.Annotator
import com.intellij.lang.annotation.HighlightSeverity
import com.intellij.openapi.editor.DefaultLanguageHighlighterColors
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import org.jetbrains.uast.UExpression
import org.jetbrains.uast.ULiteralExpression
import org.jetbrains.uast.UPolyadicExpression
import org.jetbrains.uast.toUElementOfType
class LoggingPlaceholderAnnotator : Annotator {
override fun annotate(element: PsiElement, holder: AnnotationHolder) {
val literalExpression = element.toUElementOfType<UExpression>() ?: return
if (literalExpression !is ULiteralExpression && literalExpression !is UPolyadicExpression) return
val ranges = getRanges(literalExpression) ?: return
val offset = element.textRange.startOffset
ranges.forEach { range ->
val shiftedRange = range.shiftRight(offset)
holder.newSilentAnnotation(HighlightSeverity.TEXT_ATTRIBUTES).range(shiftedRange).textAttributes(DefaultLanguageHighlighterColors.VALID_STRING_ESCAPE).create()
}
}
private fun getRanges(uExpression: UExpression): List<TextRange>? {
val context = getContext(uExpression) ?: return null
var rangeList = getPlaceholderRanges(context)?.flatMap {
val ranges = it.ranges
if (ranges.any { range -> range == null }) return null
ranges.filterNotNull()
} ?: return null
val placeholderParametersSize = context.placeholderParameters.size
if (placeholderParametersSize < rangeList.size) {
rangeList = rangeList.dropLast(rangeList.size - placeholderParametersSize)
}
return getAlignedPlaceholderCount(rangeList, context)
}
}

View File

@@ -29,7 +29,6 @@ fun getLogArgumentReferences(uExpression: UExpression): List<PsiSymbolReference>
val ranges = getPlaceholderRanges(context) ?: return null
val psiLiteralExpression = uExpression.sourcePsi ?: return null
val placeholderParametersSize = context.placeholderParameters.size
val loggerReferenceList = ranges.zip(context.placeholderParameters) { placeholderRanges, parameter ->
val parameterPsi = parameter.sourcePsi ?: return null
@@ -39,23 +38,7 @@ fun getLogArgumentReferences(uExpression: UExpression): List<PsiSymbolReference>
}
}.flatten()
return when (context.loggerType) {
SLF4J -> {
loggerReferenceList.take(if (context.lastArgumentIsException) placeholderParametersSize - 1 else placeholderParametersSize)
}
LOG4J_OLD_STYLE, LOG4J_FORMATTED_STYLE -> {
if (context.lastArgumentIsException && placeholderParametersSize == 1) {
emptyList()
}
else {
loggerReferenceList
}
}
SLF4J_EQUAL_PLACEHOLDERS, LOG4J_EQUAL_PLACEHOLDERS -> {
loggerReferenceList
}
else -> null
}
return getAlignedPlaceholderCount(loggerReferenceList, context)
}
internal fun getContext(uExpression: UExpression): PlaceholderContext? {
@@ -67,6 +50,27 @@ internal fun getContext(uExpression: UExpression): PlaceholderContext? {
return context
}
internal fun <T> getAlignedPlaceholderCount(placeholderList: List<T>, context: PlaceholderContext): List<T>? {
val placeholderParametersSize = context.placeholderParameters.size
return when (context.loggerType) {
SLF4J -> {
placeholderList.take(if (context.lastArgumentIsException) placeholderParametersSize - 1 else placeholderParametersSize)
}
LOG4J_OLD_STYLE, LOG4J_FORMATTED_STYLE -> {
if (context.lastArgumentIsException && placeholderParametersSize == 1) {
emptyList()
}
else {
placeholderList
}
}
SLF4J_EQUAL_PLACEHOLDERS, LOG4J_EQUAL_PLACEHOLDERS -> {
placeholderList
}
else -> null
}
}
internal fun getPlaceholderRanges(context: PlaceholderContext): List<PlaceholderRanges>? {
val logStringText = context.logStringArgument.sourcePsi?.text ?: return null
val partHolders = listOf(