[kotlin] Run Kotlin JVM tests on both K1 and K2 frontend

#IDEA-354810 Fixed


(cherry picked from commit d29d3256472dfe368161335732ded20ae95cf34e)

IJ-MR-140910

GitOrigin-RevId: 0a9b3cae7aab473f732012ad91b4e67f97ff8697
This commit is contained in:
Bart van Helvert
2024-07-25 00:03:40 +02:00
committed by intellij-monorepo-bot
parent db79e0d621
commit 72b748d5e0
290 changed files with 1604 additions and 844 deletions

View File

@@ -0,0 +1,198 @@
package com.intellij.codeInspection.tests.kotlin.logging
import com.intellij.analysis.JvmAnalysisBundle
import com.intellij.jvm.analysis.internal.testFramework.logging.LoggingConditionDisagreesWithLogLevelStatementInspectionTestBase
import com.intellij.jvm.analysis.testFramework.JvmLanguage
import org.jetbrains.kotlin.idea.base.plugin.KotlinPluginModeProvider
abstract class KotlinLoggingConditionDisagreesWithLogLevelStatementInspectionTest : LoggingConditionDisagreesWithLogLevelStatementInspectionTestBase(), KotlinPluginModeProvider {
fun `test slf4j`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.LoggerFactory
internal class X {
fun n() {
if (LOG.isInfoEnabled) {
LOG.info("nothing to report")
}
if (LOG.<warning descr="Level of condition 'INFO' does not match level of logging call 'WARN'">isInfoEnabled</warning>) {
LOG.warn("test")
}
if (LOG.<warning descr="Level of condition 'INFO' does not match level of logging call 'WARN'">isInfoEnabled</warning>()) {
LOG.warn("test")
}
}
companion object {
private val LOG = LoggerFactory.getLogger()
}
}
""".trimIndent())
}
fun `test log4j2`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.apache.logging.log4j.LogManager
internal class Y {
fun m() {
if (LOG.isWarnEnabled()) {
LOG.warn("test")
}
if (LOG.isWarnEnabled ) {
LOG.warn("test")
}
if (LOG.<warning descr="Level of condition 'INFO' does not match level of logging call 'WARN'">isInfoEnabled</warning> ) {
LOG.warn("test")
}
if (LOG.<warning descr="Level of condition 'INFO' does not match level of logging call 'WARN'">isInfoEnabled</warning>()) {
LOG.warn("test")
}
}
companion object {
val LOG = LogManager.getLogger()
}
}
""".trimIndent())
}
fun `test several logs`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal object X {
private val logger = LoggerFactory.getLogger()
fun test1() {
if (logger.isDebugEnabled) {
try {
something()
logger.debug("a")
} catch (e: Exception) {
logger.error("a")
}
}
if (logger.isDebugEnabled()) {
try {
something()
logger.debug("a")
} catch (e: Exception) {
logger.error("a")
}
}
if (logger.<warning descr="Level of condition 'INFO' does not match level of logging call 'DEBUG'"><warning descr="Level of condition 'INFO' does not match level of logging call 'ERROR'">isInfoEnabled</warning></warning>) {
try {
something()
logger.debug("a")
} catch (e: Exception) {
logger.error("a")
}
}
if (logger.<warning descr="Level of condition 'INFO' does not match level of logging call 'DEBUG'"><warning descr="Level of condition 'INFO' does not match level of logging call 'ERROR'">isInfoEnabled</warning></warning>()) {
try {
something()
logger.debug("a")
} catch (e: Exception) {
logger.error("a")
}
}
}
private fun something() {}
}
""".trimIndent())
}
fun `test java util logging`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import java.util.logging.Level
import java.util.logging.Logger
val LOG = Logger.getLogger("")
internal class Loggers {
fun method() {
if (LOG.<warning descr="Level of condition 'FINE' does not match level of logging call 'WARNING'">isLoggable</warning>(Level.FINE)) {
LOG.warning("test")
}
if (LOG.isLoggable(Level.WARNING)) {
LOG.warning("not error")
}
}
}
""".trimIndent())
}
fun `test fixes slf4j change guards`() {
myFixture.testQuickFix(
testPreview = true,
lang = JvmLanguage.KOTLIN,
before = """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal object Slf4J {
private val log: Logger = LoggerFactory.getLogger(Slf4J::class.java)
private fun request1(i: String) {
val msg = "log messages2: {}"
if (log.isDeb<caret>ugEnabled) {
log.info(msg, i)
}
}
}""".trimIndent(),
after = """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal object Slf4J {
private val log: Logger = LoggerFactory.getLogger(Slf4J::class.java)
private fun request1(i: String) {
val msg = "log messages2: {}"
if (log.isInfoEnabled) {
log.info(msg, i)
}
}
}""".trimIndent(),
hint = JvmAnalysisBundle.message("jvm.inspection.logging.condition.disagrees.with.log.statement.fix.name", 0)
)
}
fun `test fixes slf4j change guards as methods`() {
myFixture.testQuickFix(
testPreview = true,
lang = JvmLanguage.KOTLIN,
before = """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal object Slf4J {
private val log: Logger = LoggerFactory.getLogger(Slf4J::class.java)
private fun request1(i: String) {
val msg = "log messages2: {}"
if (log.isDeb<caret>ugEnabled()) {
log.info(msg, i)
}
}
}""".trimIndent(),
after = """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal object Slf4J {
private val log: Logger = LoggerFactory.getLogger(Slf4J::class.java)
private fun request1(i: String) {
val msg = "log messages2: {}"
if (log.isInfoEnabled()) {
log.info(msg, i)
}
}
}""".trimIndent(),
hint = JvmAnalysisBundle.message("jvm.inspection.logging.condition.disagrees.with.log.statement.fix.name", 0)
)
}
}

View File

@@ -0,0 +1,289 @@
package com.intellij.codeInspection.tests.kotlin.logging
import com.intellij.analysis.JvmAnalysisBundle
import com.intellij.jvm.analysis.internal.testFramework.logging.LoggingGuardedByConditionInspectionTestBase
import com.intellij.jvm.analysis.testFramework.JvmLanguage
import org.jetbrains.kotlin.idea.base.plugin.KotlinPluginModeProvider
abstract class KotlinLoggingGuardedByConditionInspectionTest : LoggingGuardedByConditionInspectionTestBase(), KotlinPluginModeProvider {
fun `test slf4j`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
fun n(arg: String) {
if (LOG.<warning descr="Logging call guarded by log condition">isDebugEnabled</warning>) {
LOG.debug("test" + arg)
}
}
companion object {
private val LOG: Logger = LoggerFactory.getLogger()
}
}
""".trimIndent())
}
fun `test log4j2`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger
internal class X {
fun n(arg: String) {
if (LOG.<warning descr="Logging call guarded by log condition">isDebugEnabled()</warning>) {
LOG.debug("test1" + arg)
}
}
companion object {
val LOG: Logger = LogManager.getLogger()
}
}
""".trimIndent())
}
fun `test several calls slf4j`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
fun n(arg: String) {
if (LOG.<warning descr="Logging call guarded by log condition">isDebugEnabled</warning>) {
LOG.debug("test1" + arg)
LOG.debug("test2" + arg)
}
}
companion object {
private val LOG: Logger = LoggerFactory.getLogger()
}
}
""".trimIndent())
}
fun `test several different calls slf4j`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
fun n(arg: String) {
if (LOG.<warning descr="Logging call guarded by log condition">isDebugEnabled</warning>) {
LOG.info("test1" + arg)
LOG.debug("test2" + arg)
}
}
companion object {
private val LOG: Logger = LoggerFactory.getLogger()
}
}
""".trimIndent())
}
fun `test several calls with another call slf4j`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
fun n(arg: String) {
if (LOG.<warning descr="Logging call guarded by log condition">isDebugEnabled</warning>) {
LOG.debug("test1" + arg)
arg.toString()
}
}
companion object {
private val LOG: Logger = LoggerFactory.getLogger()
}
}
""".trimIndent())
}
fun `test several calls with another call slf4j showOnlyIfFixPossible`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
fun n(arg: String) {
if (LOG.isDebugEnabled) {
LOG.debug("test1" + arg)
arg.toString()
}
}
companion object {
private val LOG: Logger = LoggerFactory.getLogger()
}
}
""".trimIndent())
}
fun `test slf4j fix`() {
myFixture.testQuickFix(
testPreview = true,
lang = JvmLanguage.KOTLIN,
before = """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
fun n(arg: String) {
if (LOG.<caret>isDebugEnabled) {
LOG.debug("test" + arg)
}
}
companion object {
private val LOG: Logger = LoggerFactory.getLogger()
}
}
""".trimIndent(),
after = """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
fun n(arg: String) {
LOG.debug("test" + arg)
}
companion object {
private val LOG: Logger = LoggerFactory.getLogger()
}
}
""".trimIndent(),
hint = JvmAnalysisBundle.message("jvm.inspection.log.guarded.fix.family.name")
)
}
fun `test slf4j without block fix`() {
myFixture.testQuickFix(
testPreview = true,
lang = JvmLanguage.KOTLIN,
before = """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
fun n(arg: String) {
if (LOG.<caret>isDebugEnabled)
LOG.debug("test" + arg)
}
companion object {
private val LOG: Logger = LoggerFactory.getLogger()
}
}
""".trimIndent(),
after = """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
fun n(arg: String) {
LOG.debug("test" + arg)
}
companion object {
private val LOG: Logger = LoggerFactory.getLogger()
}
}""".trimIndent(),
hint = JvmAnalysisBundle.message("jvm.inspection.log.guarded.fix.family.name")
)
}
fun `test several calls slf4j fix`() {
myFixture.testQuickFix(
testPreview = true,
lang = JvmLanguage.KOTLIN,
before = """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
fun n(arg: String) {
if (LOG.<caret>isDebugEnabled) {
LOG.debug("test1" + arg)
LOG.debug("test2" + arg)
}
}
companion object {
private val LOG: Logger = LoggerFactory.getLogger()
}
}
""".trimIndent(),
after = """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
fun n(arg: String) {
LOG.debug("test1" + arg)
LOG.debug("test2" + arg)
}
companion object {
private val LOG: Logger = LoggerFactory.getLogger()
}
}
""".trimIndent(),
hint = JvmAnalysisBundle.message("jvm.inspection.log.guarded.fix.family.name")
)
}
fun `test slf4j with comment fix`() {
myFixture.testQuickFix(
testPreview = true,
lang = JvmLanguage.KOTLIN,
before = """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
fun n(arg: String) {
if (LOG.<caret>isDebugEnabled) {//comment1
//comment2
LOG.debug("test" + arg)
//comment3
//comment4
}
}
companion object {
private val LOG: Logger = LoggerFactory.getLogger()
}
}
""".trimIndent(),
after = """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
fun n(arg: String) {
//comment1
//comment2
LOG.debug("test" + arg)
//comment3
//comment4
}
companion object {
private val LOG: Logger = LoggerFactory.getLogger()
}
}
""".trimIndent(),
hint = JvmAnalysisBundle.message("jvm.inspection.log.guarded.fix.family.name")
)
}
}

View File

@@ -0,0 +1,225 @@
package com.intellij.codeInspection.tests.kotlin.logging
import com.intellij.jvm.analysis.internal.testFramework.logging.LoggingPlaceholderCountMatchesArgumentCountInspectionTestBase
import com.intellij.jvm.analysis.testFramework.JvmLanguage
import org.jetbrains.kotlin.idea.base.plugin.KotlinPluginModeProvider
abstract class KotlinLoggingPlaceholderCountMatchesArgumentCountInspectionLog4J2Test : LoggingPlaceholderCountMatchesArgumentCountInspectionTestBase(), KotlinPluginModeProvider {
fun `test log4j2 with text variables`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.apache.logging.log4j.LogManager
internal class Logging {
fun m(i: Int) {
val text = "test {}{}{}"
LOG.info( <warning descr="Fewer arguments provided (1) than placeholders specified (3)">text</warning> , i)
val text2 = "test "
LOG.fatal( <warning descr="More arguments provided (1) than placeholders specified (0)">text2</warning> , i)
LOG.fatal( <warning descr="Fewer arguments provided (1) than placeholders specified (6)">text + text</warning> , i)
LOG.fatal( <warning descr="Fewer arguments provided (1) than placeholders specified (18)">text + text + text + text + text + text</warning> , i)
LOG.info( <warning descr="More arguments provided (1) than placeholders specified (0)">FINAL_TEXT</warning> , i)
val sum = "first {}" + "second {}" + 1
LOG.info( <warning descr="Fewer arguments provided (1) than placeholders specified (2)">sum</warning> , i)
}
companion object {
private const val FINAL_TEXT = "const"
private val LOG = LogManager.getLogger()
}
}
""".trimIndent())
}
fun `test log4j2`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.apache.logging.log4j.*;
private val logger = LogManager.getLogger();
private val brackets: String = "{}"
fun foo() {
logger?.debug(<warning descr="Fewer arguments provided (2) than placeholders specified (3)">"test {} {} {}"</warning>, 1, 2) //warn
logger?.debug(<warning descr="More arguments provided (2) than placeholders specified (1)">"test " + brackets</warning>, 1, 2) //warn
logger?.debug("test {}" + brackets, 1, 2)
logger?.debug(<warning descr="Fewer arguments provided (1) than placeholders specified (3)">"test {} {} {}"</warning>, 1, Exception()) //warn
logger?.debug(<warning descr="More arguments provided (1) than placeholders specified (0)">"test"</warning>, 1, Exception()) //warn
logger?.debug(<warning descr="Fewer arguments provided (0) than placeholders specified (1)">"test {}"</warning>, Exception()) //warn
logger?.debug("test {} {}", 1, 2, Exception())
logger?.debug("test {} {}", 1, Exception())
logger?.debug(<warning descr="Fewer arguments provided (2) than placeholders specified (3)">"test {} {} {}"</warning>, 1, 2) //warn
logger?.debug("test {} {}", 1, 2, Exception())
logger?.debug(<warning descr="More arguments provided (2) than placeholders specified (1)">"test {}"</warning>, 1, 2) //warn
logger?.error(<warning descr="Fewer arguments provided (2) than placeholders specified (3)">"test {} {} {}"</warning>, 1, 2) //warn
logger?.fatal(<warning descr="Fewer arguments provided (2) than placeholders specified (3)">"test {} {} {}"</warning>, 1, 2) //warn
logger?.info(<warning descr="Fewer arguments provided (2) than placeholders specified (3)">"test {} {} {}"</warning>, 1, 2) //warn
logger?.trace(<warning descr="Fewer arguments provided (2) than placeholders specified (3)">"test {} {} {}"</warning>, 1, 2) //warn
logger?.warn(<warning descr="Fewer arguments provided (2) than placeholders specified (3)">"test {} {} {}"</warning>, 1, 2) //warn
logger?.info("test {} {}", {}, {}, {RuntimeException()})
logger?.info("test {} {}", {}, {RuntimeException()})
}
""".trimIndent())
}
fun `test log4j2 builder`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.apache.logging.log4j.*;
private val logger = LogManager.getLogger();
private val brackets: String = "{}"
fun foo() {
logger?.atDebug()?.log(<warning descr="Fewer arguments provided (2) than placeholders specified (3)">"test {} {} {}"</warning>, 1, 2) //warn
logger?.atDebug()?.log("test {} {}", 1, 2)
logger?.atDebug()?.log(<warning descr="More arguments provided (2) than placeholders specified (0)">"test"</warning>, 1, Exception()) //warn
logger?.atDebug()?.log(<warning descr="Fewer arguments provided (2) than placeholders specified (3)">"test {} {} {}"</warning>, 1, Exception()) //warn
logger?.atDebug()?.log("test {} {} {}", 1, 2, Exception())
logger?.atDebug()?.log(<warning descr="More arguments provided (3) than placeholders specified (2)">"test {} {}"</warning>, 1, 2, Exception()) //warn
logger?.atDebug()?.log("test {}", Exception())
logger?.atDebug()?.log(<warning descr="More arguments provided (1) than placeholders specified (0)">"test"</warning>, Exception()) //warn
}
internal class Logging {
fun m(i: Int) {
LOG.atInfo().log( <warning descr="Fewer arguments provided (1) than placeholders specified (3)">"test? {}{}{}"</warning> , i)
LOG.atFatal().log( <warning descr="More arguments provided (2) than placeholders specified (0)">"test "</warning> , i, i)
}
companion object {
private val LOG = LogManager.getLogger()
}
}
""".trimIndent())
}
fun `test log4j2LogBuilder 2`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.util.Supplier
internal class Logging {
fun m(i: Int) {
LOG.atInfo().log( <warning descr="Fewer arguments provided (1) than placeholders specified (3)">"test? {}{}{}"</warning> , i)
LOG.atFatal().log( <warning descr="More arguments provided (2) than placeholders specified (0)">"test "</warning> , i, i)
LOG.atError().log( <warning descr="More arguments provided (1) than placeholders specified (0)">"test? "</warning> , Supplier<Any> { "" })
}
companion object {
private val LOG = LogManager.getLogger()
}
}
""".trimIndent())
}
fun `test formatted log4j`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.apache.logging.log4j.*;
private val LOG: Logger = LogManager.getFormatterLogger()
fun m() {
try {
throw RuntimeException()
} catch (t: Throwable) {
val LOG2: Logger = LogManager.getFormatterLogger()
LOG.info("My %s text", "test", t)
LOG.info( <warning descr="Illegal format string specifier">"My %i text"</warning> , "test")
LOG.info( <warning descr="More arguments provided (2) than placeholders specified (1)">"My %s text"</warning> , "test1", "test2")
LOG2.info("My %s text, %s", "test1") //skip because LOG2 is not final
LogManager.getFormatterLogger().info( <warning descr="Fewer arguments provided (1) than placeholders specified (2)">"My %s text, %s"</warning> , "test1")
}
}
""".trimIndent())
}
fun `test Log4j2 with exception in suppliers`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.util.Supplier
internal class Logging {
fun m() {
try {
throw java.lang.RuntimeException()
} catch (t: IllegalArgumentException) {
LOG.info( <warning descr="More arguments provided (3) than placeholders specified (1)">"test {}"</warning> , Supplier<Any> { "test" }, Supplier<Any> { "test" }, Supplier<Any> { t })
} catch (t: IllegalStateException) {
LOG.info(<warning descr="More arguments provided (3) than placeholders specified (1)">"test {}"</warning>, Supplier<Any> { "test" }, Supplier<Any> { "test" }, Supplier<Any> { t })
} catch (t: Throwable) {
LOG.info("test {}", Supplier<Any> { "test" }, Supplier<Any> { t })
LOG.info( <warning descr="More arguments provided (3) than placeholders specified (1)">"test {}"</warning> , Supplier<Any> { "test" }, Supplier<Any> { "test" }, Supplier<Any> { t })
val s = Supplier { t }
LOG.info("test {}", Supplier<Any> { "test" }, s)
val s2: Supplier<*> = Supplier<Any> { t }
LOG.info("test {}", Supplier<Any> { "test" }, s2)
val s3: Supplier<*> = Supplier { t }
LOG.info("test {}", Supplier<Any> { "test" }, s3)
LOG.info("test {}", Supplier<Any> { "test" }, Supplier<Any> { RuntimeException() })
LOG.info("test {}", Supplier<Any> { "test" })
LOG.info(<warning descr="More arguments provided (2) than placeholders specified (1)">"test {}"</warning>, {""}, {" "})
LOG.info("test {}", {""}, {RuntimeException()})
val function: () -> String = { "RuntimeException()" }
LOG.info(<warning descr="More arguments provided (2) than placeholders specified (1)">"test {}"</warning>, {""}, function)
val function2: () -> RuntimeException = { RuntimeException() }
LOG.info("test {}", {""}, function2)
}
}
companion object {
private val LOG = LogManager.getLogger()
}
}
""".trimIndent())
}
fun `test error type`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.apache.logging.log4j.LogManager
class Log4j {
fun m() {
var e = <error descr="[UNRESOLVED_REFERENCE] Unresolved reference: Ce">Ce</error>;
LOG.error(<warning descr="Fewer arguments provided (2) than placeholders specified (3)">"1 {} {} {}"</warning> , <error descr="[DEBUG] Resolved to error element">e</error>, <error descr="[DEBUG] Resolved to error element">e</error>)
}
companion object {
val LOG = LogManager.getLogger()
}
}
""".trimIndent())
}
fun `test formatted log4j with partial known strings`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.apache.logging.log4j.LogManager
internal object Logging {
private val logger = LogManager.getFormatterLogger()
fun test(t: String) {
logger.info( <warning descr="Fewer arguments provided (0) than placeholders specified (at least 1)">"%s" + t + 1 + "%s "</warning> )
logger.info( <warning descr="Fewer arguments provided (0) than placeholders specified (at least 2)">"%s %s" + t + 1</warning> )
logger.info(<warning descr="Fewer arguments provided (1) than placeholders specified (2)">"%s %s"</warning>, 1)
logger.atDebug().log("%s t", 1)
val logBuilder = logger.atDebug()
logBuilder.log(<warning descr="More arguments provided (2) than placeholders specified (0)">"%s t"</warning>, 1, 2)
logger.info(<warning descr="More arguments provided (2) than placeholders specified (1)">"%s t"</warning>, 2, 2)
logger.info("%s t", 2)
logger.info(<warning descr="More arguments provided (2) than placeholders specified (1)">"%s t"</warning>, 2, 3)
}
}
""".trimIndent())
}
fun `test log4j with partial known strings`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.apache.logging.log4j.LogManager
internal object Logging {
private val logger = LogManager.getLogger()
fun test(t: String) {
logger.info( <warning descr="Fewer arguments provided (0) than placeholders specified (at least 2)">"{}" + t + 1 + "{}"</warning> )
logger.info( <warning descr="Fewer arguments provided (0) than placeholders specified (at least 2)">"{}" + t + 1 + "{}"</warning> , RuntimeException())
logger.info( <warning descr="Fewer arguments provided (1) than placeholders specified (at least 3)">"{} {}" + t + 1 + "{}"</warning> , 1, RuntimeException())
logger.info("{}" + t + 1 + "{}", 1, RuntimeException())
logger.info("{}" + t + 1 + "{}", 1, 1)
}
}
""".trimIndent())
}
}

View File

@@ -0,0 +1,206 @@
package com.intellij.codeInspection.tests.kotlin.logging
import com.intellij.codeInspection.logging.LoggingPlaceholderCountMatchesArgumentCountInspection
import com.intellij.jvm.analysis.internal.testFramework.logging.LoggingPlaceholderCountMatchesArgumentCountInspectionTestBase
import com.intellij.jvm.analysis.testFramework.JvmLanguage
import org.jetbrains.kotlin.idea.base.plugin.KotlinPluginModeProvider
abstract class KotlinLoggingPlaceholderCountMatchesArgumentCountInspectionPlaceholderNumberTest : LoggingPlaceholderCountMatchesArgumentCountInspectionTestBase(), KotlinPluginModeProvider {
fun `test many variables`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.LoggerFactory
internal class X {
var LOGGER = LoggerFactory.getLogger()
fun m() {
val a1 = " {} " +" s"
val a2 = a1 + a1 + a1 + a1 + a1 + a1 + a1 + a1 + a1
LOGGER.info( <warning descr="Fewer arguments provided (1) than placeholders specified (at least 3)">"abd"+a2</warning> , 1)
}
}
""".trimIndent())
}
fun `test variables`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.LoggerFactory
private const val con = "{}"
internal class X {
var logger = LoggerFactory.getLogger()
private var con2 = "{}"
private fun slf4jVariable3(number: String) {
logger.info(<warning descr="Fewer arguments provided (1) than placeholders specified (at least 2)">number + "1 {} {}"</warning>, 1) //warn
logger.info(<warning descr="Fewer arguments provided (1) than placeholders specified (at least 2)">number + "1 {} {}"</warning>, 1) //warn
var t = "{}"
logger.info(con2 + t + "1", 1)
logger.info(con2 + t + "1", 1)
}
private fun slf4jVariable(number: String) {
logger.info(<warning descr="Fewer arguments provided (1) than placeholders specified (at least 2)">number + "1 {} {}"</warning>, 1) //warn
logger.info(<warning descr="Fewer arguments provided (1) than placeholders specified (at least 2)">number + "1 {} {}"</warning>, 1) //warn
var t = "{}"
logger.info(<warning descr="Fewer arguments provided (1) than placeholders specified (2)">con + t + "1"</warning>, 1) //warn
logger.info(<warning descr="Fewer arguments provided (1) than placeholders specified (2)">con + t + "1"</warning>, 1) //warn
}
private fun slf4jVariable2(number: String) {
logger.info(<warning descr="Fewer arguments provided (1) than placeholders specified (at least 2)">number + "1 {} {}"</warning>, 1) //warn
logger.info(<warning descr="Fewer arguments provided (1) than placeholders specified (at least 2)">number + "1 {} {}"</warning>, 1) //warn
var t = "{}"
logger.info(con + t + "1", 1)
t = "1"
logger.info(con + t + "1", 1)
}
}
""".trimIndent())
}
fun `test fewer and more placeholders`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.*;
internal class X {
fun foo() {
val logger = LoggerFactory.getLogger()
logger.info( <warning descr="Fewer arguments provided (1) than placeholders specified (2)">"string {}{}"</warning> , 1)
logger.info( <warning descr="More arguments provided (1) than placeholders specified (0)">"string"</warning> , 1)
}
}
""".trimIndent())
}
fun `test escaping`() {
inspection.slf4jToLog4J2Type = LoggingPlaceholderCountMatchesArgumentCountInspection.Slf4jToLog4J2Type.NO
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.LoggerFactory
internal class X {
var LOG = LoggerFactory.getLogger()
fun m() {
LOG.info("Created key {}\\\\{}", 1, 2)
LOG.info( <warning descr="More arguments provided (2) than placeholders specified (1)">"Created key {}\\{}"</warning> , 1, 2)
}
}
""".trimIndent())
}
fun `test non constant string`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.LoggerFactory
internal class X {
val LOG = LoggerFactory.getLogger()
fun m() {
LOG.info( <warning descr="Fewer arguments provided (0) than placeholders specified (4)">S + "{}" + (1 + 2) + '{' + '}' + S</warning> )
LOG.info( <warning descr="Fewer arguments provided (0) than placeholders specified (1)">message</warning> )
}
companion object {
private const val message = "HELLO {}"
private const val S = "{}"
}
}
""".trimIndent())
}
fun `test 1 exception and several placeholder`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.LoggerFactory
internal class X {
fun foo() {
val e = RuntimeException()
LoggerFactory.getLogger().info( <warning descr="Fewer arguments provided (0) than placeholders specified (1)">"this: {}"</warning> , e)
LoggerFactory.getLogger().info("1: {} e: {}", 1, e)
LoggerFactory.getLogger().info( <warning descr="Fewer arguments provided (1) than placeholders specified (3)">"1: {} {} {}"</warning> , 1, e)
val logger = LoggerFactory.getLogger()
logger.info("string {}", 1)
}
}
""".trimIndent())
}
fun `test throwable`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.LoggerFactory
internal class X {
fun foo() {
val logger = LoggerFactory.getLogger()
logger.info("string {}", 1, RuntimeException())
}
}
""".trimIndent())
}
fun `test multi catch`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.LoggerFactory
internal class X {
fun multiCatch() {
try {
method()
} catch (e: FirstException) {
logger.info("failed with first or second", e)
} catch (e: SecondException) {
logger.info("failed with first or second", e)
}
}
fun method() {
}
class FirstException : Exception()
class SecondException : Exception()
companion object {
private val logger = LoggerFactory.getLogger()
}
}
""".trimIndent())
}
fun `test no slf4j`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
internal class FalsePositiveSLF4J {
fun method(definitelyNotSLF4J: DefinitelyNotSLF4J) {
definitelyNotSLF4J.info("not a trace message", "not a trace parameter")
}
interface DefinitelyNotSLF4J {
fun info(firstParameter: String?, secondParameter: Any?)
}
}
""".trimIndent())
}
fun `test array argument`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.LoggerFactory
internal class X {
var LOG = LoggerFactory.getLogger()
fun m(a: String, b: Int, c: Any) {
LOG.info("test {} for test {} in test {}", *arrayOf(a, b, c))
}
}
""".trimIndent())
}
fun `test uncountable array`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.LoggerFactory
internal class X {
var LOG = LoggerFactory.getLogger()
fun m(objects: Array<Any?>) {
LOG.info("test {} test text {} text {}", *objects)
}
}
""".trimIndent())
}
}

View File

@@ -0,0 +1,167 @@
package com.intellij.codeInspection.tests.kotlin.logging
import com.intellij.codeInspection.logging.LoggingPlaceholderCountMatchesArgumentCountInspection
import com.intellij.jvm.analysis.internal.testFramework.logging.LoggingPlaceholderCountMatchesArgumentCountInspectionTestBase
import com.intellij.jvm.analysis.testFramework.JvmLanguage
import org.jetbrains.kotlin.idea.base.plugin.KotlinPluginModeProvider
abstract class KotlinLoggingPlaceholderCountMatchesArgumentCountInspectionSlf4JTest : LoggingPlaceholderCountMatchesArgumentCountInspectionTestBase(), KotlinPluginModeProvider {
fun `test slf4j disable slf4jToLog4J2Type`() {
inspection.slf4jToLog4J2Type = LoggingPlaceholderCountMatchesArgumentCountInspection.Slf4jToLog4J2Type.NO
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.LoggerFactory
internal class X {
fun foo(s: String) {
val logger = LoggerFactory.getLogger()
logger.info( <warning descr="Fewer arguments provided (1) than placeholders specified (2)">"string {} {}"</warning> , 1, RuntimeException())
logger.info(<warning descr="Fewer arguments provided (1) than placeholders specified (at least 2)">s + "string {} {}"</warning> , 1, RuntimeException())
logger.info(s + "string {} {}" , 1, 2)
logger.atError().log( <warning descr="Fewer arguments provided (0) than placeholders specified (1)">"{}"</warning> , RuntimeException("test"))
LoggerFactory.getLogger().atError().log( <warning descr="Fewer arguments provided (1) than placeholders specified (2)">"{} {}"</warning> , 1, RuntimeException("test"))
LoggerFactory.getLogger().atError().log("{}", 1, RuntimeException("test"))
LoggerFactory.getLogger().atError().log(s + "{}", 1, RuntimeException("test"))
LoggerFactory.getLogger().atError().log(s + "{}", 1, 2)
LoggerFactory.getLogger().atError().log(<warning descr="More arguments provided (1) than placeholders specified (0)">""</warning>, 1, RuntimeException("test"))
LoggerFactory.getLogger().atError().log(<warning descr="Fewer arguments provided (1) than placeholders specified (at least 2)">s + "{} {} {}"</warning>, 1, RuntimeException("test"))
}
}
""".trimIndent())
}
fun `test slf4j auto slf4jToLog4J2Type`() {
inspection.slf4jToLog4J2Type = LoggingPlaceholderCountMatchesArgumentCountInspection.Slf4jToLog4J2Type.AUTO
myFixture.addClass("""
package org.apache.logging.slf4j;
public interface Log4jLogger {
}
""".trimIndent())
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.LoggerFactory
internal class X {
fun foo() {
val logger = LoggerFactory.getLogger()
logger.info("string {} {}", 1, RuntimeException())
logger.atError().log("{}", RuntimeException("test"))
LoggerFactory.getLogger().atError().log("{} {}", 1, RuntimeException("test"))
LoggerFactory.getLogger().atError().log( <warning descr="More arguments provided (2) than placeholders specified (1)">"{}"</warning> , 1, RuntimeException("test"))
}
}
""".trimIndent())
}
fun `test slf4j`() {
inspection.slf4jToLog4J2Type = LoggingPlaceholderCountMatchesArgumentCountInspection.Slf4jToLog4J2Type.NO
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.*;
private val logger: Logger? = null
private val brackets: String = "{}"
fun foo() {
logger?.debug(<warning descr="Fewer arguments provided (2) than placeholders specified (3)">"test {} {} {}"</warning>, 1, 2) //warn
logger?.debug("test {} {}", *arrayOf(1, 2))
logger?.debug("test {} {}", *arrayOf(1, 2, Exception()))
logger?.debug(<warning descr="More arguments provided (2) than placeholders specified (1)">"test " + brackets</warning>, 1, 2) //warn
logger?.debug("test {}" + brackets, 1, 2)
logger?.debug("test {} {}", 1, 2)
logger?.debug(<warning descr="Fewer arguments provided (1) than placeholders specified (2)">"test {} \\{} {}"</warning>, 1) //warn
logger?.debug("test {} \\{} {}", 1, 2)
logger?.debug(<warning descr="Fewer arguments provided (1) than placeholders specified (2)">"test {} {}"</warning>, 1, Exception()) //warn
logger?.debug("test {} {}", 1, 2, Exception())
logger?.debug(<warning descr="Fewer arguments provided (2) than placeholders specified (3)">"test {} {} {}"</warning>, 1, 2) //warn
logger?.debug(<warning descr="More arguments provided (2) than placeholders specified (1)">"test {}"</warning>, 1, 2) //warn
logger?.error(<warning descr="Fewer arguments provided (2) than placeholders specified (3)">"test {} {} {}"</warning>, 1, 2) //warn
logger?.info(<warning descr="Fewer arguments provided (2) than placeholders specified (3)">"test {} {} {}"</warning>, 1, 2) //warn
logger?.trace(<warning descr="Fewer arguments provided (2) than placeholders specified (3)">"test {} {} {}"</warning>, 1, 2) //warn
logger?.warn(<warning descr="Fewer arguments provided (2) than placeholders specified (3)">"test {} {} {}"</warning>, 1, 2) //warn
}
""".trimIndent())
}
fun `test slf4j with partial known strings`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.LoggerFactory
import java.util.*
internal class X {
var logger = LoggerFactory.getLogger()
fun m(t: String) {
logger.info("{} {}", 1, 2)
logger.info( <warning descr="Fewer arguments provided (0) than placeholders specified (at least 2)">"{}" + t + 1 + "{}"</warning> )
logger.info( <warning descr="Fewer arguments provided (0) than placeholders specified (at least 1)">"{}" + t + 1</warning> )
logger.info( <warning descr="Fewer arguments provided (0) than placeholders specified (at least 1)">"{}${'$'}t{}"</warning> )
logger.info("{}${'$'}t{}", 1, 2)
logger.info("{}${'$'}t{}", 1, 2, 3)
val temp1 = "{} {}${'$'}t"
var temp = "{} {}${'$'}t"
logger.info( <warning descr="Fewer arguments provided (1) than placeholders specified (at least 2)">temp1</warning> , 1)
logger.info(temp, 1, 2, 3)
logger.info(logText, 1, 2, 3)
logger.info( <warning descr="Fewer arguments provided (1) than placeholders specified (at least 2)">logText</warning> , 1)
logger.info( <warning descr="Fewer arguments provided (1) than placeholders specified (at least 3)">logText2</warning> , 1)
logger.info( <warning descr="Fewer arguments provided (1) than placeholders specified (3)">logText3</warning> , 1)
temp = "{}${'$'}t"
logger.info(temp, 1)
}
fun m(i: Int, s: String) {
logger.info( <warning descr="Fewer arguments provided (0) than placeholders specified (1)">"test1 {}"</warning> )
logger.info( <warning descr="Fewer arguments provided (0) than placeholders specified (at least 1)">"test1 {}${'$'}s"</warning> )
logger.info( <warning descr="Fewer arguments provided (0) than placeholders specified (1)">"test1 {}${'$'}i"</warning> )
}
companion object {
private val logText = "{} {}" + something
private val logText2 = "{} {}" + 1 + "{}" + something
private const val logText3 = "{} {}" + 1 + "{}"
private val something: String
get() = if (Random().nextBoolean()) "{}" else ""
}
}
""".trimIndent())
}
fun `test slf4j builder`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.LoggerFactory
import org.slf4j.spi.LoggingEventBuilder
fun foo() {
LoggerFactory.getLogger().atError().log("{}", RuntimeException("test"))
LoggerFactory.getLogger().atError().log("{} {}", 1, RuntimeException("test"))
LoggerFactory.getLogger().atError().log( <warning descr="More arguments provided (2) than placeholders specified (1)">"{}"</warning> , 1, RuntimeException("test"))
logger2.atError().log(<warning descr="Fewer arguments provided (1) than placeholders specified (2)">"{} {}"</warning>, 1)
val loggingEventBuilder = logger2.atError()
loggingEventBuilder
.log("{} {}", 2) //skip, because it can be complex cases
logger2.atError()
.log(<warning descr="Fewer arguments provided (1) than placeholders specified (2)">"{} {}"</warning>, 2) //warn
logger2.atError()
.addArgument("s")
.addKeyValue("1", "1")
.log("{} {}", 2)
logger2.atError()
.setMessage(<warning descr="Fewer arguments provided (0) than placeholders specified (2)">"{} {}"</warning>)
.log()
logger2.atError()
.addArgument("")
.addArgument("")
.setMessage("{} {}")
.log()
}
private val logger2 = LoggerFactory.getLogger()
private val builder: LoggingEventBuilder = logger2.atError()
""".trimIndent())
}
}

View File

@@ -0,0 +1,116 @@
package com.intellij.codeInspection.tests.kotlin.logging
import com.intellij.jvm.analysis.internal.testFramework.logging.LoggingSimilarMessageInspectionTestBase
import com.intellij.jvm.analysis.testFramework.JvmLanguage
import org.jetbrains.kotlin.idea.base.plugin.KotlinPluginModeProvider
abstract class KotlinLoggingSimilarMessageInspectionTest : LoggingSimilarMessageInspectionTestBase(), KotlinPluginModeProvider {
fun `test equals log4j2`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger
internal class Logging {
private val logger: Logger = LogManager.getLogger()
private fun request1(i: String) {
val msg = "log messages: {}"
logger.<weak_warning descr="Similar log messages">info(msg, i)</weak_warning>
}
private fun request2(i: Int) {
val msg = "log messages: {}"
logger.<weak_warning descr="Similar log messages">info(msg, i)</weak_warning>
}
}
""".trimIndent())
}
fun `test equals slf4j`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class Logging {
private val LOG: Logger = LoggerFactory.getLogger(Logging::class.<error descr="[UNRESOLVED_REFERENCE] Unresolved reference: java">java</error>)
private fun request1(i: String) {
val msg = "log messages: {}"
LOG.<weak_warning descr="Similar log messages">info(msg, i)</weak_warning>
LOG.info("1" + msg, i)
}
private fun request2(i: Int) {
val msg = "log messages: {}"
LOG.<weak_warning descr="Similar log messages">info(msg, i)</weak_warning>
}
}
""".trimIndent())
}
fun `test setMessage slf4j`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class Logging {
private val LOG: Logger = LoggerFactory.getLogger(Logging::class.<error descr="[UNRESOLVED_REFERENCE] Unresolved reference: java">java</error>)
private fun request1(i: String) {
val msg = "log messages: {}" + i
LOG.atInfo().setCause(RuntimeException()).setMessage(msg).log()
LOG.atInfo().setMessage(msg).<weak_warning descr="Similar log messages">log()</weak_warning>
}
private fun request2(i: Int) {
val msg = "log messages: {}" + i
LOG.atInfo().setCause(RuntimeException()).setMessage(msg).log()
LOG.atInfo().setMessage(msg).<weak_warning descr="Similar log messages">log()</weak_warning>
}
}
""".trimIndent())
}
fun `test skip in the middle parts`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class Logging {
private val LOG: Logger = LoggerFactory.getLogger(Logging::class.<error descr="[UNRESOLVED_REFERENCE] Unresolved reference: java">java</error>)
private fun request1(i: String) {
val msg = "${"\${i}"}1234356${"\${i}"}"
LOG.info(msg)
}
private fun request2(i: Int) {
val msg = "something 1234356${"\${i}"}"
LOG.info(msg)
}
}
""".trimIndent())
}
fun `test skip inside calls`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class Logging {
private val LOG: Logger = LoggerFactory.getLogger(Logging::class.<error descr="[UNRESOLVED_REFERENCE] Unresolved reference: java">java</error>)
private fun request2() {
LOG.warn("Non-cached operation ${"\${operationName(\"update\")}"}")
LOG.warn("Non-cached operation ${"\${operationName(\"getChildren\")}"}")
}
private fun operationName(operationName: String): String {
return operationName
}
}
""".trimIndent())
}
}

View File

@@ -0,0 +1,330 @@
package com.intellij.codeInspection.tests.kotlin.logging
import com.intellij.analysis.JvmAnalysisBundle
import com.intellij.jvm.analysis.internal.testFramework.logging.LoggingStatementNotGuardedByLogConditionInspectionTestBase
import com.intellij.jvm.analysis.testFramework.JvmLanguage
import org.jetbrains.kotlin.idea.base.plugin.KotlinPluginModeProvider
abstract class KotlinLoggingStatementNotGuardedByLogConditionInspectionTest : LoggingStatementNotGuardedByLogConditionInspectionTestBase(), KotlinPluginModeProvider {
fun `test slf4j`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
private val LOG = LoggerFactory.getLogger()
fun n(arg: String) {
<warning descr="Logging call not guarded by a logging condition">LOG.debug("test {}", arg)</warning>
}
}
""".trimIndent())
}
fun `test log4j2`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger
internal class X {
fun n(arg: String) {
<warning descr="Logging call not guarded by a logging condition">LOG.debug("test {}", arg)</warning>
}
companion object {
val LOG: Logger = LogManager.getLogger()
}
}
""".trimIndent())
}
fun `test skip according level for slf4j`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
fun n(arg: String) {
LOG.warn("test " + arg)
}
companion object {
private val LOG: Logger = LoggerFactory.getLogger()
}
}
""".trimIndent())
}
fun `test is surrounded by guard for slf4j`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
fun n(arg: String) {
if (LOG.isDebugEnabled) {
LOG.debug("test " + arg)
}
if (LOG.isInfoEnabled) {
<warning descr="Logging call not guarded by a logging condition">LOG.debug("test" + arg)</warning> //todo!
}
if (true && LOG.isDebugEnabled) {
LOG.debug("test {}", arg)
}
if (true && LOG.isDebugEnabled) {
if (true) {
LOG.debug("test {}", arg)
}
}
}
companion object {
private val LOG: Logger = LoggerFactory.getLogger()
}
}
""".trimIndent())
}
fun `test skip if only constant arguments for slf4j`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
fun n() {
LOG.debug("test")
LOG.debug("test {} {}", "test" + "test", 1 + 1)
}
companion object {
private val LOG: Logger = LoggerFactory.getLogger()
}
}
""".trimIndent())
}
fun `test don't skip if only constant arguments for slf4j flagUnguardedConstant`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
fun n1() {
<warning descr="Logging call not guarded by a logging condition">LOG.debug("test")</warning>
}
fun n2() {
<warning descr="Logging call not guarded by a logging condition">LOG.debug("test")</warning>
}
companion object {
private val LOG: Logger = LoggerFactory.getLogger()
}
}
""".trimIndent())
}
fun `test skip with several log calls for slf4j`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
fun n2(arg: String) {
<warning descr="Logging call not guarded by a logging condition">LOG.debug("test1" + arg)</warning>
LOG.debug("test2" + arg)
}
fun n3(arg: String) {
<warning descr="Logging call not guarded by a logging condition">LOG.debug("test1" + arg)</warning>
LOG.debug("test2" + arg)
LOG.debug("test2" + arg)
}
fun constantCall(arg: String) {
LOG.debug("test1")
<warning descr="Logging call not guarded by a logging condition">LOG.debug("test2" + arg)</warning>
}
fun beforeNotLog(arg: String) {
constantCall(arg)
<warning descr="Logging call not guarded by a logging condition">LOG.debug("test2" + arg)</warning>
}
fun differentLevels(arg: String) {
<warning descr="Logging call not guarded by a logging condition">LOG.debug("test1" + arg)</warning>
LOG.warn("test2" + arg)
}
companion object {
private val LOG: Logger = LoggerFactory.getLogger()
}
}
""".trimIndent())
}
fun `test fix simple slf4j`() {
myFixture.testQuickFix(
testPreview = true,
lang = JvmLanguage.KOTLIN,
before = """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
fun n(arg: String) {
LOG.<caret>debug("test" + arg)
}
companion object {
private val LOG: Logger = LoggerFactory.getLogger()
}
}
""".trimIndent(),
after = """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
fun n(arg: String) {
if (LOG.isDebugEnabled) {
LOG.debug("test" + arg)
}
}
companion object {
private val LOG: Logger = LoggerFactory.getLogger()
}
}
""".trimIndent(),
hint = JvmAnalysisBundle.message("jvm.inspection.log.statement.not.guarded.log.fix.family.name")
)
}
fun `test fix simple nested slf4j`() {
myFixture.testQuickFix(
testPreview = false,
lang = JvmLanguage.KOTLIN,
before = """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
fun n(arg: String) {
if(true){
LOG.<caret>debug("test" + arg)
}
}
companion object {
private val LOG: Logger = LoggerFactory.getLogger()
}
}
""".trimIndent(),
after = """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
fun n(arg: String) {
if(true){
if (LOG.isDebugEnabled) {
LOG.debug("test" + arg)
}
}
}
companion object {
private val LOG: Logger = LoggerFactory.getLogger()
}
}
""".trimIndent(),
hint = JvmAnalysisBundle.message("jvm.inspection.log.statement.not.guarded.log.fix.family.name")
)
}
fun `test fix several similar slf4j`() {
myFixture.testQuickFix(
testPreview = true,
lang = JvmLanguage.KOTLIN,
before = """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
fun n(arg: String) {
LOG.<caret>debug("test1" + arg)
LOG.debug("test2" + arg)
}
companion object {
private val LOG: Logger = LoggerFactory.getLogger()
}
}
""".trimIndent(),
after = """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
fun n(arg: String) {
if (LOG.isDebugEnabled) {
LOG.debug("test1" + arg)
LOG.debug("test2" + arg)
}
}
companion object {
private val LOG: Logger = LoggerFactory.getLogger()
}
}
""".trimIndent(),
hint = JvmAnalysisBundle.message("jvm.inspection.log.statement.not.guarded.log.fix.family.name")
)
}
fun `test fix several different slf4j`() {
myFixture.testQuickFix(
testPreview = true,
lang = JvmLanguage.KOTLIN,
before = """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
fun n(arg: String) {
LOG.<caret>debug("test1" + arg)
LOG.debug("test2" + arg)
LOG.info("test3" + arg)
}
companion object {
private val LOG: Logger = LoggerFactory.getLogger()
}
}
""".trimIndent(),
after = """
import org.slf4j.Logger
import org.slf4j.LoggerFactory
internal class X {
fun n(arg: String) {
if (LOG.isDebugEnabled) {
LOG.debug("test1" + arg)
LOG.debug("test2" + arg)
}
LOG.info("test3" + arg)
}
companion object {
private val LOG: Logger = LoggerFactory.getLogger()
}
}
""".trimIndent(),
hint = JvmAnalysisBundle.message("jvm.inspection.log.statement.not.guarded.log.fix.family.name")
)
}
}

View File

@@ -0,0 +1,86 @@
package com.intellij.codeInspection.tests.kotlin.logging
import com.intellij.codeInspection.logging.LoggingStringTemplateAsArgumentInspection
import com.intellij.codeInspection.logging.LoggingUtil
import com.intellij.jvm.analysis.KotlinJvmAnalysisTestUtil
import com.intellij.jvm.analysis.internal.testFramework.logging.LoggingStringTemplateAsArgumentInspectionTestBase
import com.intellij.testFramework.TestDataPath
import org.jetbrains.kotlin.idea.base.plugin.KotlinPluginModeProvider
private const val INSPECTION_PATH = "/codeInspection/logging/stringTemplateAsArgument"
@TestDataPath("\$CONTENT_ROOT/testData$INSPECTION_PATH")
abstract class KotlinLoggingStringTemplateAsArgumentInspectionTest : LoggingStringTemplateAsArgumentInspectionTestBase(), KotlinPluginModeProvider {
override val inspection: LoggingStringTemplateAsArgumentInspection = LoggingStringTemplateAsArgumentInspection().apply {
myLimitLevelType = LoggingUtil.LimitLevelType.ALL
}
override fun getBasePath() = KotlinJvmAnalysisTestUtil.TEST_DATA_PROJECT_RELATIVE_BASE_PATH + INSPECTION_PATH
private fun withSettings(
skipPrimitives: Boolean = inspection.mySkipPrimitives,
levelType: LoggingUtil.LimitLevelType = inspection.myLimitLevelType,
skipWithTheOnlyException: Boolean = inspection.mySkipWithTheOnlyException,
test: () -> Unit
) {
val curSkipPrimitives = inspection.mySkipPrimitives
val curLimitLevelType = inspection.myLimitLevelType
val curSkipWithTheOnlyException = inspection.mySkipWithTheOnlyException
try {
inspection.mySkipPrimitives = skipPrimitives
inspection.myLimitLevelType = levelType
inspection.mySkipWithTheOnlyException = skipWithTheOnlyException
test()
} finally {
inspection.mySkipPrimitives = curSkipPrimitives
inspection.myLimitLevelType = curLimitLevelType
inspection.mySkipWithTheOnlyException = curSkipWithTheOnlyException
}
}
fun `test default settings highlighting, with guards`() {
myFixture.testHighlighting("StringTemplateAsArgumentGuarded.kt")
}
fun `test highlighting info and lower no skip primitives`() {
withSettings(skipPrimitives = false, levelType = LoggingUtil.LimitLevelType.INFO_AND_LOWER) {
myFixture.testHighlighting("StringTemplateAsArgumentWarnInfo.kt")
}
}
fun `test highlighting debug no skip primitives`() {
withSettings(skipPrimitives = false, LoggingUtil.LimitLevelType.DEBUG_AND_LOWER) {
myFixture.testHighlighting("StringTemplateAsArgumentWarnDebug.kt")
}
}
fun `test highlighting all skip primitives`() {
withSettings(skipPrimitives = true, LoggingUtil.LimitLevelType.ALL) {
myFixture.testHighlighting("StringTemplateAsArgumentSkipPrimitives.kt")
}
}
fun `test highlighting all no skip primitives`() {
withSettings(skipPrimitives = false, LoggingUtil.LimitLevelType.ALL) {
myFixture.testHighlighting("StringTemplateAsArgument.kt")
}
}
fun `test fix all no skip primitives`() {
withSettings(skipPrimitives = false, LoggingUtil.LimitLevelType.ALL) {
myFixture.testQuickFix("StringTemplateAsArgumentFix.kt", checkPreview = true)
}
}
fun `test fix with escape symbol all no skip primitives`() {
withSettings(skipPrimitives = false, LoggingUtil.LimitLevelType.ALL) {
myFixture.testQuickFix("StringTemplateAsArgumentWithEscapeSymbolsFix.kt", checkPreview = true)
}
}
fun `test highlighting all no skip primitives skip with the only exception`() {
withSettings(skipPrimitives = false, LoggingUtil.LimitLevelType.ALL, skipWithTheOnlyException = true) {
myFixture.testHighlighting("StringTemplateAsArgumentSkipException.kt")
}
}
}