mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-03-22 15:19:59 +07:00
[Java. Logging] Restore support for escape symbols in LoggingArgumentSymbolReferenceProvider
IDEA-342484 GitOrigin-RevId: 68d3e58e45554128c59d0a81d4d24ad415b8b812
This commit is contained in:
committed by
intellij-monorepo-bot
parent
1831451cdb
commit
0e73acf094
@@ -2,8 +2,6 @@
|
||||
package com.intellij.analysis.logging.resolve
|
||||
|
||||
import com.intellij.codeInspection.logging.*
|
||||
import com.intellij.codeInspection.logging.PlaceholderCountIndexStrategy.KOTLIN_MULTILINE_RAW_STRING
|
||||
import com.intellij.codeInspection.logging.PlaceholderCountIndexStrategy.RAW_STRING
|
||||
import com.intellij.codeInspection.logging.PlaceholderLoggerType.*
|
||||
import com.intellij.model.Symbol
|
||||
import com.intellij.model.psi.PsiExternalReferenceHost
|
||||
@@ -73,7 +71,17 @@ 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 else RAW_STRING
|
||||
val type = if (isKotlinMultilineString(context.logStringArgument, logStringText)) {
|
||||
KOTLIN_MULTILINE_RAW_STRING
|
||||
}
|
||||
else if (isKotlinString(context.logStringArgument)) {
|
||||
KOTLIN_RAW_STRING
|
||||
}
|
||||
else if (isJavaString(context.logStringArgument)) {
|
||||
JAVA_RAW_STRING
|
||||
}
|
||||
else return null
|
||||
|
||||
val partHolders = listOf(
|
||||
LoggingStringPartEvaluator.PartHolder(
|
||||
logStringText,
|
||||
@@ -86,6 +94,14 @@ internal fun getPlaceholderRanges(context: PlaceholderContext): List<Placeholder
|
||||
return placeholderCountResult.placeholderRangesList
|
||||
}
|
||||
|
||||
private fun isKotlinMultilineString(logString: UExpression, text : String): Boolean {
|
||||
return logString is UPolyadicExpression && text.startsWith("\"\"\"") && text.endsWith("\"\"\"") && text.length >= 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, PlaceholderCountIndexStrategy.UAST_STRING)
|
||||
val placeholderCountHolder = solvePlaceholderCount(context.loggerType, finalArgumentCount, context.partHolderList, UAST_STRING)
|
||||
|
||||
if (placeholderCountHolder.status == PlaceholdersStatus.EMPTY) {
|
||||
return true
|
||||
|
||||
@@ -124,24 +124,35 @@ internal enum class PlaceholdersStatus {
|
||||
EXACTLY, PARTIAL, ERROR_TO_PARSE_STRING, EMPTY
|
||||
}
|
||||
|
||||
internal enum class PlaceholderCountIndexStrategy {
|
||||
UAST_STRING {
|
||||
override fun shiftAfterEscapeChar(index: Int): Int {
|
||||
return index
|
||||
}
|
||||
},
|
||||
KOTLIN_MULTILINE_RAW_STRING {
|
||||
override fun shiftAfterEscapeChar(index: Int): Int {
|
||||
return index
|
||||
}
|
||||
},
|
||||
RAW_STRING {
|
||||
override fun shiftAfterEscapeChar(index: Int): Int {
|
||||
return index + 1
|
||||
}
|
||||
};
|
||||
internal interface PlaceholderCountIndexStrategy {
|
||||
fun shiftAfterEscapeChar(text: String, index: Int): Int {
|
||||
assert(index in text.indices && text[index] == '\\')
|
||||
return index
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun shiftAfterEscapeChar(index: Int): Int
|
||||
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
|
||||
}
|
||||
|
||||
private fun isEscapeSymbol(char: Char): Boolean = char in escapeSymbols
|
||||
}
|
||||
|
||||
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', '\'', '\"')
|
||||
}
|
||||
|
||||
|
||||
@@ -468,17 +479,17 @@ private fun countBracesBasedPlaceholders(holders: List<LoggingStringPartEvaluato
|
||||
full = false
|
||||
continue
|
||||
}
|
||||
val string = partHolder.text ?: continue
|
||||
val length = string.length
|
||||
val text = partHolder.text ?: continue
|
||||
val length = text.length
|
||||
var escaped = false
|
||||
var lastPlaceholderIndex = -1
|
||||
var i = 0
|
||||
while (i < length) {
|
||||
val c = string[i]
|
||||
val c = text[i]
|
||||
if (c == '\\' &&
|
||||
(loggerType == PlaceholderLoggerType.SLF4J_EQUAL_PLACEHOLDERS || loggerType == PlaceholderLoggerType.SLF4J)) {
|
||||
escaped = !escaped
|
||||
i = placeholderCountShiftIndexStrategy.shiftAfterEscapeChar(i)
|
||||
i = placeholderCountShiftIndexStrategy.shiftAfterEscapeChar(text, i)
|
||||
}
|
||||
else if (c == '{') {
|
||||
if (holderIndex != 0 && i == 0 && !holders[holderIndex - 1].isConstant) {
|
||||
|
||||
@@ -465,63 +465,96 @@ class JavaLoggingArgumentSymbolReferenceProviderTest : LoggingArgumentSymbolRefe
|
||||
doTest(emptyMap())
|
||||
}
|
||||
|
||||
fun `test should resolve with escape character in simple string log4j2`() {
|
||||
fun `test resolve with escape characters in simple string log4j2`() {
|
||||
myFixture.configureByText("Logging.java", """
|
||||
import org.apache.logging.log4j.*;
|
||||
class Logging {
|
||||
private static final Logger LOG = LogManager.getLogger();
|
||||
void m(int i) {
|
||||
LOG.info("\\{<caret>}", i);
|
||||
LOG.info("\"{} \'{<caret>} \f{} \t{} \b{} \n{} \r{} \\{}", 1, 2, 3, 4, 5, 6, 7, 8);
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
doTest(mapOf(TextRange(3, 5) to "i"))
|
||||
doTest(mapOf(
|
||||
TextRange(3, 5) to "1",
|
||||
TextRange(8, 10) to "2",
|
||||
TextRange(13, 15) to "3",
|
||||
TextRange(18, 20) to "4",
|
||||
TextRange(23, 25) to "5",
|
||||
TextRange(28, 30) to "6",
|
||||
TextRange(33, 35) to "7",
|
||||
TextRange(38, 40) to "8",
|
||||
))
|
||||
}
|
||||
|
||||
fun `test should resolve with escape character in multiline string log4j2`() {
|
||||
fun `test resolve with escape characters in multiline string log4j2`() {
|
||||
val multilineString = "\"\"\"\n" +
|
||||
"\\\\{<caret>}" +
|
||||
"\\\"{} \\'{<caret>} \\f{} \\t{} \\b{} \\n{} \\r{} \\\\{}" +
|
||||
"\"\"\""
|
||||
myFixture.configureByText("Logging.java", """
|
||||
import org.apache.logging.log4j.*;
|
||||
class Logging {
|
||||
private static final Logger LOG = LogManager.getLogger();
|
||||
void m(int i) {
|
||||
LOG.info($multilineString, i);
|
||||
LOG.info($multilineString, 1, 2, 3, 4, 5, 6, 7, 8);
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
doTest(mapOf(TextRange(6, 8) to "i"))
|
||||
doTest(mapOf(
|
||||
TextRange(6, 8) to "1",
|
||||
TextRange(11, 13) to "2",
|
||||
TextRange(16, 18) to "3",
|
||||
TextRange(21, 23) to "4",
|
||||
TextRange(26, 28) to "5",
|
||||
TextRange(31, 33) to "6",
|
||||
TextRange(36, 38) to "7",
|
||||
TextRange(41, 43) to "8",
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun `test should not resolve with escape character in simple string slf4j`() {
|
||||
fun `test resolve with escape characters in simple string slf4j`() {
|
||||
myFixture.configureByText("Logging.java", """
|
||||
import org.slf4j.*;
|
||||
class Logging {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Logging.class);
|
||||
void m(int i) {
|
||||
LOG.info("\\{<caret>}", i);
|
||||
LOG.info("\"{} \'{<caret>} \f{} \t{} \b{} \n{} \r{} \\{}", 1, 2, 3, 4, 5, 6, 7);
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
doTest(emptyMap())
|
||||
doTest(mapOf(
|
||||
TextRange(3, 5) to "1",
|
||||
TextRange(8, 10) to "2",
|
||||
TextRange(13, 15) to "3",
|
||||
TextRange(18, 20) to "4",
|
||||
TextRange(23, 25) to "5",
|
||||
TextRange(28, 30) to "6",
|
||||
TextRange(33, 35) to "7",
|
||||
))
|
||||
}
|
||||
|
||||
fun `test should not resolve with escape character in multiline string slf4j`() {
|
||||
|
||||
fun `test resolve with escape characters in multiline string slf4j`() {
|
||||
val multilineString = "\"\"\"\n" +
|
||||
"\\\\{<caret>}" +
|
||||
"\\\"{} \\'{<caret>} \\f{} \\t{} \\b{} \\n{} \\r{} \\\\{}" +
|
||||
"\"\"\""
|
||||
myFixture.configureByText("Logging.java", """
|
||||
import org.slf4j.*;
|
||||
class Logging {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Logging.class);
|
||||
void m(int i) {
|
||||
LOG.info($multilineString, i);
|
||||
LOG.info($multilineString, 1, 2, 3, 4, 5, 6, 7);
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
doTest(emptyMap())
|
||||
doTest(mapOf(
|
||||
TextRange(6, 8) to "1",
|
||||
TextRange(11, 13) to "2",
|
||||
TextRange(16, 18) to "3",
|
||||
TextRange(21, 23) to "4",
|
||||
TextRange(26, 28) to "5",
|
||||
TextRange(31, 33) to "6",
|
||||
TextRange(36, 38) to "7",
|
||||
))
|
||||
}
|
||||
}
|
||||
@@ -483,63 +483,96 @@ class KotlinLoggingArgumentSymbolReferenceProviderTest : LoggingArgumentSymbolRe
|
||||
doTest(emptyMap())
|
||||
}
|
||||
|
||||
fun `test should resolve with escape character in simple string log4j2`() {
|
||||
fun `test resolve with escape characters in simple string log4j2`() {
|
||||
myFixture.configureByText("Logging.kt", """
|
||||
import org.apache.logging.log4j.*
|
||||
class Logging {
|
||||
val LOG: Logger = LoggerFactory.getLogger(Logging.class)
|
||||
val LOG: Logger = LogManager.getLogger(Logging.class)
|
||||
fun m(i: Int) {
|
||||
LOG.info("\\{<caret>}", i)
|
||||
LOG.info("\"{} \'{<caret>} \${"$"}{} \t{} \b{} \n{} \r{} \\{}", 1, 2, 3, 4, 5, 6, 7, 8)
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
doTest(mapOf(TextRange(3, 5) to "i"))
|
||||
doTest(mapOf(
|
||||
TextRange(3, 5) to "1",
|
||||
TextRange(8, 10) to "2",
|
||||
TextRange(13, 15) to "3",
|
||||
TextRange(18, 20) to "4",
|
||||
TextRange(23, 25) to "5",
|
||||
TextRange(28, 30) to "6",
|
||||
TextRange(33, 35) to "7",
|
||||
TextRange(38, 40) to "8",
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
fun `test should resolve with escape character in multiline string log4j2`() {
|
||||
fun `test resolve with escape characters in multiline string log4j2`() {
|
||||
val multilineString = "\"\"\"\n" +
|
||||
"\\\\{<caret>}" +
|
||||
"\\\"{} \\'{<caret>} \\t{} \\b{} \\n{} \\r{} \\\\{}" +
|
||||
"\"\"\""
|
||||
myFixture.configureByText("Logging.kt", """
|
||||
import org.apache.logging.log4j.*
|
||||
class Logging {
|
||||
val LOG: Logger = LoggerFactory.getLogger(Logging.class)
|
||||
val LOG: Logger = LogManager.getLogger(Logging.class)
|
||||
fun m(i: Int) {
|
||||
LOG.info("$multilineString", i)
|
||||
LOG.info("$multilineString", 1, 2, 3, 4, 5, 6, 7)
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
doTest(mapOf(TextRange(7, 9) to "i"))
|
||||
doTest(mapOf(
|
||||
TextRange(7, 9) to "1",
|
||||
TextRange(12, 14) to "2",
|
||||
TextRange(17, 19) to "3",
|
||||
TextRange(22, 24) to "4",
|
||||
TextRange(27, 29) to "5",
|
||||
TextRange(32, 34) to "6",
|
||||
TextRange(37, 39) to "7",
|
||||
))
|
||||
}
|
||||
|
||||
fun `test should not resolve with escape character in simple string slf4j`() {
|
||||
fun `test resolve with escape characters in simple string slf4j`() {
|
||||
myFixture.configureByText("Logging.kt", """
|
||||
import org.slf4j.*
|
||||
class Logging {
|
||||
val LOG: Logger = LogManager.getFormatterLogger()
|
||||
val LOG: Logger = LoggerFactory.getLogger()
|
||||
fun m(i: Int) {
|
||||
LOG.info("\\{<caret>}", i)
|
||||
LOG.info("\"{} \'{<caret>} \${"$"}{} \t{} \b{} \n{} \r{} \\{}", 1, 2, 3, 4, 5, 6, 7)
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
doTest(emptyMap())
|
||||
doTest(mapOf(
|
||||
TextRange(3, 5) to "1",
|
||||
TextRange(8, 10) to "2",
|
||||
TextRange(13, 15) to "3",
|
||||
TextRange(18, 20) to "4",
|
||||
TextRange(23, 25) to "5",
|
||||
TextRange(28, 30) to "6",
|
||||
TextRange(33, 35) to "7",
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
fun `test should resolve with escape character in multiline string slf4j`() {
|
||||
fun `test resolve with escape characters in multiline string slf4j`() {
|
||||
val multilineString = "\"\"\"\n" +
|
||||
"\\\\{<caret>}" +
|
||||
"\\\"{} \\'{<caret>} \\t{} \\b{} \\n{} \\r{} \\\\{}" +
|
||||
"\"\"\""
|
||||
myFixture.configureByText("Logging.kt", """
|
||||
import org.slf4j.*
|
||||
class Logging {
|
||||
val LOG: Logger = LoggerFactory.getLogger(Logging.class)
|
||||
val LOG: Logger = LoggerFactory.getLogger()
|
||||
fun m(i: Int) {
|
||||
LOG.info("$multilineString", i)
|
||||
LOG.info("$multilineString", 1, 2, 3, 4, 5, 6, 7)
|
||||
}
|
||||
}
|
||||
""".trimIndent())
|
||||
doTest(mapOf(TextRange(7, 9) to "i"))
|
||||
doTest(mapOf(
|
||||
TextRange(7, 9) to "1",
|
||||
TextRange(12, 14) to "2",
|
||||
TextRange(17, 19) to "3",
|
||||
TextRange(22, 24) to "4",
|
||||
TextRange(27, 29) to "5",
|
||||
TextRange(32, 34) to "6",
|
||||
TextRange(37, 39) to "7",
|
||||
))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user