mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-03-22 15:10:43 +07:00
[Java. Logging] Add better way to check if SLF4J log placeholder is located before backslash
IDEA-342484 GitOrigin-RevId: 2e1646050dfcec175d282d4ccadb3b20bbe8da0e
This commit is contained in:
committed by
intellij-monorepo-bot
parent
71ddef194d
commit
1367dfa422
@@ -72,15 +72,11 @@ internal fun <T> getAlignedPlaceholderCount(placeholderList: List<T>, context: P
|
||||
internal fun getPlaceholderRanges(context: PlaceholderContext): List<PlaceholderRanges>? {
|
||||
val logStringText = context.logStringArgument.sourcePsi?.text ?: return null
|
||||
val type = if (isKotlinMultilineString(context.logStringArgument, logStringText)) {
|
||||
KOTLIN_MULTILINE_RAW_STRING
|
||||
PlaceholderEscapeSymbolStrategy.KOTLIN_RAW_MULTILINE_STRING
|
||||
}
|
||||
else if (isKotlinString(context.logStringArgument)) {
|
||||
KOTLIN_RAW_STRING
|
||||
else {
|
||||
PlaceholderEscapeSymbolStrategy.RAW_STRING
|
||||
}
|
||||
else if (isJavaString(context.logStringArgument)) {
|
||||
JAVA_RAW_STRING
|
||||
}
|
||||
else return null
|
||||
|
||||
val partHolders = listOf(
|
||||
LoggingStringPartEvaluator.PartHolder(
|
||||
@@ -98,10 +94,6 @@ private fun isKotlinString(logString: UExpression): Boolean {
|
||||
return logString is UPolyadicExpression
|
||||
}
|
||||
|
||||
private fun isJavaString(logString: UExpression): Boolean {
|
||||
return logString is ULiteralExpression
|
||||
}
|
||||
|
||||
private fun isKotlinMultilineString(logString: UExpression, text: String): Boolean {
|
||||
return isKotlinString(logString) && text.startsWith("\"\"\"") && text.endsWith("\"\"\"") && text.length >= 6
|
||||
}
|
||||
@@ -56,7 +56,7 @@ class LoggingPlaceholderCountMatchesArgumentCountInspection : AbstractBaseUastLo
|
||||
|
||||
var finalArgumentCount = context.placeholderParameters.size
|
||||
|
||||
val placeholderCountHolder = solvePlaceholderCount(context.loggerType, finalArgumentCount, context.partHolderList, UAST_STRING)
|
||||
val placeholderCountHolder = solvePlaceholderCount(context.loggerType, finalArgumentCount, context.partHolderList, PlaceholderEscapeSymbolStrategy.UAST_STRING)
|
||||
|
||||
if (placeholderCountHolder.status == PlaceholdersStatus.EMPTY) {
|
||||
return true
|
||||
|
||||
@@ -124,38 +124,44 @@ internal enum class PlaceholdersStatus {
|
||||
EXACTLY, PARTIAL, ERROR_TO_PARSE_STRING, EMPTY
|
||||
}
|
||||
|
||||
internal interface PlaceholderCountIndexStrategy {
|
||||
fun shiftAfterEscapeChar(text: String, index: Int): Int {
|
||||
assert(index in text.indices && text[index] == '\\')
|
||||
return index
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Enum class representing different strategies for escaping placeholder symbols in a string.
|
||||
* For SLF4J, logger placeholders might be treated as regular symbols if they are located after '\' character.
|
||||
* For example, ```log.info("\{}", id)``` will print "{}" string.
|
||||
*/
|
||||
internal enum class PlaceholderEscapeSymbolStrategy {
|
||||
RAW_STRING {
|
||||
override fun isPlaceholderAfterBackslash(text: String, index: Int): Boolean {
|
||||
val backslashCount = countBackslashes(text, index)
|
||||
return backslashCount == 2
|
||||
}
|
||||
},
|
||||
KOTLIN_RAW_MULTILINE_STRING {
|
||||
override fun isPlaceholderAfterBackslash(text: String, index: Int): Boolean {
|
||||
val backslashCount = countBackslashes(text, index)
|
||||
return backslashCount == 1
|
||||
}
|
||||
},
|
||||
UAST_STRING {
|
||||
override fun isPlaceholderAfterBackslash(text: String, index: Int): Boolean {
|
||||
val backslashCount = countBackslashes(text, index)
|
||||
return backslashCount == 1
|
||||
}
|
||||
};
|
||||
|
||||
internal abstract class RawStringPlaceholderCountStrategy : PlaceholderCountIndexStrategy {
|
||||
protected abstract val escapeSymbols: Set<Char>
|
||||
|
||||
override fun shiftAfterEscapeChar(text: String, index: Int): Int {
|
||||
assert(index in text.indices && text[index] == '\\')
|
||||
if (index + 1 !in text.indices || isEscapeSymbol(text[index + 1])) return index
|
||||
return index + 1
|
||||
protected fun countBackslashes(text: String, index: Int): Int {
|
||||
var count = 0
|
||||
for (i in index downTo 0) {
|
||||
if (count > 10) return count
|
||||
if (text[i] == '\\') count += 1
|
||||
else return count
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
private fun isEscapeSymbol(char: Char): Boolean = char in escapeSymbols
|
||||
abstract fun isPlaceholderAfterBackslash(text: String, index: Int): Boolean
|
||||
}
|
||||
|
||||
internal val UAST_STRING = object : PlaceholderCountIndexStrategy {}
|
||||
|
||||
internal val KOTLIN_MULTILINE_RAW_STRING = object : PlaceholderCountIndexStrategy {}
|
||||
|
||||
internal val KOTLIN_RAW_STRING = object : RawStringPlaceholderCountStrategy() {
|
||||
override val escapeSymbols: Set<Char> = setOf('t', 'b', 'n', 'r', '$', '\'', '\"')
|
||||
}
|
||||
|
||||
internal val JAVA_RAW_STRING = object : RawStringPlaceholderCountStrategy() {
|
||||
override val escapeSymbols: Set<Char> = setOf('t', 'b', 'n', 'r', 'f', '\'', '\"')
|
||||
}
|
||||
|
||||
|
||||
internal class LoggerContext(val log4jAsImplementationForSlf4j: Boolean)
|
||||
|
||||
/**
|
||||
@@ -331,7 +337,7 @@ internal fun findAdditionalArguments(node: UCallExpression,
|
||||
* @param loggerType The type of the logger used.
|
||||
* @param argumentCount The number of arguments that the logger is expected to handle.
|
||||
* @param holders The list of PartHolder objects representing logging string parts.
|
||||
* @param placeholderCountShiftIndexStrategy The strategy of shifting index for escape backslash during parsing SLF4J placeholders. It is different for regular string and psi text
|
||||
* @param placeholderEscapeSymbolStrategy The strategy of shifting index for escape backslash during parsing SLF4J placeholders. It is different for regular string and psi text
|
||||
*
|
||||
* @return PlaceholderCountResult returns the result of either countFormattedPlaceholders or countBracesPlaceholders based on the type of the logger.
|
||||
*/
|
||||
@@ -339,13 +345,13 @@ internal fun solvePlaceholderCount(
|
||||
loggerType: PlaceholderLoggerType,
|
||||
argumentCount: Int,
|
||||
holders: List<LoggingStringPartEvaluator.PartHolder>,
|
||||
placeholderCountShiftIndexStrategy: PlaceholderCountIndexStrategy
|
||||
placeholderEscapeSymbolStrategy: PlaceholderEscapeSymbolStrategy
|
||||
): PlaceholderCountResult {
|
||||
return if (loggerType == PlaceholderLoggerType.LOG4J_FORMATTED_STYLE) {
|
||||
countFormattedBasedPlaceholders(holders, argumentCount)
|
||||
}
|
||||
else {
|
||||
countBracesBasedPlaceholders(holders, loggerType, placeholderCountShiftIndexStrategy)
|
||||
countBracesBasedPlaceholders(holders, loggerType, placeholderEscapeSymbolStrategy)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -469,7 +475,7 @@ internal fun hasThrowableType(lastArgument: UExpression): Boolean {
|
||||
|
||||
private fun countBracesBasedPlaceholders(holders: List<LoggingStringPartEvaluator.PartHolder>,
|
||||
loggerType: PlaceholderLoggerType,
|
||||
placeholderCountShiftIndexStrategy: PlaceholderCountIndexStrategy): PlaceholderCountResult {
|
||||
placeholderEscapeSymbolStrategy: PlaceholderEscapeSymbolStrategy): PlaceholderCountResult {
|
||||
var count = 0
|
||||
var full = true
|
||||
val placeholderRangeList: MutableList<PlaceholderRanges> = mutableListOf()
|
||||
@@ -480,28 +486,20 @@ private fun countBracesBasedPlaceholders(holders: List<LoggingStringPartEvaluato
|
||||
continue
|
||||
}
|
||||
val text = partHolder.text ?: continue
|
||||
val length = text.length
|
||||
var escaped = false
|
||||
var lastPlaceholderIndex = -1
|
||||
var i = 0
|
||||
while (i < length) {
|
||||
for (i in text.indices) {
|
||||
val c = text[i]
|
||||
if (c == '\\' &&
|
||||
(loggerType == PlaceholderLoggerType.SLF4J_EQUAL_PLACEHOLDERS || loggerType == PlaceholderLoggerType.SLF4J)) {
|
||||
escaped = !escaped
|
||||
i = placeholderCountShiftIndexStrategy.shiftAfterEscapeChar(text, i)
|
||||
}
|
||||
else if (c == '{') {
|
||||
if (c == '{') {
|
||||
if (holderIndex != 0 && i == 0 && !holders[holderIndex - 1].isConstant) {
|
||||
i += 1
|
||||
continue
|
||||
}
|
||||
if (!escaped) {
|
||||
lastPlaceholderIndex = i
|
||||
}
|
||||
lastPlaceholderIndex = i
|
||||
}
|
||||
else if (c == '}') {
|
||||
if (lastPlaceholderIndex != -1) {
|
||||
if (lastPlaceholderIndex != -1 && (loggerType == PlaceholderLoggerType.SLF4J_EQUAL_PLACEHOLDERS || loggerType == PlaceholderLoggerType.SLF4J) && placeholderEscapeSymbolStrategy.isPlaceholderAfterBackslash(text, lastPlaceholderIndex - 1)) {
|
||||
lastPlaceholderIndex = -1
|
||||
}
|
||||
else if (lastPlaceholderIndex != -1) {
|
||||
count++
|
||||
placeholderRangeList.add(
|
||||
PlaceholderRanges(
|
||||
@@ -512,10 +510,8 @@ private fun countBracesBasedPlaceholders(holders: List<LoggingStringPartEvaluato
|
||||
}
|
||||
}
|
||||
else {
|
||||
escaped = false
|
||||
lastPlaceholderIndex = -1
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
return PlaceholderCountResult(placeholderRangeList, if (full) PlaceholdersStatus.EXACTLY else PlaceholdersStatus.PARTIAL)
|
||||
|
||||
Reference in New Issue
Block a user